From dafd4c1aa68f8906e9aa61f15a80234ac61b3dfb Mon Sep 17 00:00:00 2001 From: tonymac32 Date: Tue, 30 Jan 2018 22:04:45 -0500 Subject: [PATCH] Rockchip remove unnecessary patches --- .../0001-aufs4.4.patch.disabled | 36286 ---------------- .../stowed/03-patch-4.4.69-70.patch | 3739 -- .../stowed/03-patch-4.4.70-71.patch | 2294 - .../stowed/03-patch-4.4.71-72.patch | 3348 -- .../stowed/03-patch-4.4.72-73.patch | 2192 - .../stowed/03-patch-4.4.73-74.patch | 1488 - .../stowed/03-patch-4.4.74-75.patch | 1018 - .../stowed/03-patch-4.4.75-76.patch | 2827 -- .../stowed/03-patch-4.4.76-77.patch | 1544 - .../stowed/03-patch-4.4.77-78.patch | 3019 -- .../stowed/03-patch-4.4.78-79.patch | 2607 -- .../stowed/03-patch-4.4.79-80.patch | 3287 -- .../stowed/03-patch-4.4.80-81.patch | 2112 - .../stowed/03-patch-4.4.81-82.patch | 330 - .../stowed/03-patch-4.4.82-83.patch | 476 - .../stowed/03-patch-4.4.83-84.patch | 761 - .../stowed/03-patch-4.4.84-85.patch | 1498 - .../stowed/03-patch-4.4.85-86.patch | 393 - .../stowed/03-patch-4.4.86-87.patch | 408 - .../stowed/03-patch-4.4.87-88.patch | 1154 - .../stowed/03-patch-4.4.88-89.patch | 2770 -- .../stowed/03-patch-4.4.89-90.patch | 1208 - .../stowed/03-patch-4.4.90-91.patch | 2284 - .../stowed/03-patch-4.4.91-92.patch | 1905 - .../stowed/03-patch-4.4.92-93.patch | 933 - .../stowed/03-patch-4.4.93-94.patch | 1389 - .../stowed/03-patch-4.4.94-95.patch | 1587 - .../stowed/03-patch-4.4.95-96.patch | 809 - .../stowed/03-patch-4.4.96-97.patch | 1525 - .../stowed/03-patch-4.4.97-98.patch | 1881 - .../stowed/03-patch-4.4.98-99.patch | 1260 - .../stowed/03-patch-4.4.99-100.patch | 2132 - .../stowed/04-patch-4.4.100-101.patch | 718 - .../stowed/04-patch-4.4.101-102.patch | 43 - .../stowed/04-patch-4.4.102-103.patch | 3014 -- 35 files changed, 94239 deletions(-) delete mode 100644 patch/kernel/rockchip-default/0001-aufs4.4.patch.disabled delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.69-70.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.70-71.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.71-72.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.72-73.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.73-74.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.74-75.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.75-76.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.76-77.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.77-78.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.78-79.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.79-80.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.80-81.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.81-82.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.82-83.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.83-84.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.84-85.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.85-86.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.86-87.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.87-88.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.88-89.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.89-90.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.90-91.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.91-92.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.92-93.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.93-94.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.94-95.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.95-96.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.96-97.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.97-98.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.98-99.patch delete mode 100644 patch/kernel/rockchip-default/stowed/03-patch-4.4.99-100.patch delete mode 100644 patch/kernel/rockchip-default/stowed/04-patch-4.4.100-101.patch delete mode 100644 patch/kernel/rockchip-default/stowed/04-patch-4.4.101-102.patch delete mode 100644 patch/kernel/rockchip-default/stowed/04-patch-4.4.102-103.patch diff --git a/patch/kernel/rockchip-default/0001-aufs4.4.patch.disabled b/patch/kernel/rockchip-default/0001-aufs4.4.patch.disabled deleted file mode 100644 index b66a9ba5f..000000000 --- a/patch/kernel/rockchip-default/0001-aufs4.4.patch.disabled +++ /dev/null @@ -1,36286 +0,0 @@ -diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs -new file mode 100644 -index 0000000..99642d1 ---- /dev/null -+++ b/Documentation/ABI/testing/debugfs-aufs -@@ -0,0 +1,50 @@ -+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_/xino0, xino1 ... xinoN -+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. -+ When the aufs mount option 'noxino' is specified, it -+ will be empty. 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 --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs -new file mode 100644 -index 0000000..82f9518 ---- /dev/null -+++ b/Documentation/ABI/testing/sysfs-aufs -@@ -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 --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README -new file mode 100644 -index 0000000..fa82b63 ---- /dev/null -+++ b/Documentation/filesystems/aufs/README -@@ -0,0 +1,393 @@ -+ -+Aufs4 -- advanced multi layered unification filesystem version 4.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 becomes totally different from -+Unionfs while keeping the basic features. -+Recently, Unionfs Version 2.x series begin taking some of the same -+approaches to aufs1's. -+Unionfs is being developed by Professor Erez Zadok at Stony Brook -+University and his team. -+ -+Aufs4 supports linux-4.0 and later, and for linux-3.x series try aufs3. -+If you want older kernel version support, try aufs2-2.6.git or -+aufs2-standalone.git repository, 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 aufs4. -+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 aufs4, aufs4-linux.git, -+aufs4-standalone.git, and aufs-util.git. Note that there is no "4" in -+"aufs-util.git." -+While the aufs-util is always necessary, you need either of aufs4-linux -+or aufs4-standalone. -+ -+The aufs4-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 aufs4 as an external kernel module. -+Several extra patches are not included in this tree. Only -+aufs4-standalone tree contains them. They are described in the later -+section "Configuration and Compilation." -+ -+On the other hand, the aufs4-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 "aufs4.x" where "x" -+represents the linux kernel version, "linux-4.x". For instance, -+"aufs4.0" is for linux-4.0. For latest "linux-4.x-rcN", use -+"aufs4.x-rcN" branch. -+ -+o aufs4-linux tree -+$ git clone --reference /your/linux/git/tree \ -+ git://github.com/sfjro/aufs4-linux.git aufs4-linux.git -+- if you don't have linux GIT tree, then remove "--reference ..." -+$ cd aufs4-linux.git -+$ git checkout origin/aufs4.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 aufs4 git://github.com/sfjro/aufs4-linux.git -+$ git fetch aufs4 -+$ git checkout -b my4.0 v4.0 -+$ (add your local change...) -+$ git pull aufs4 aufs4.0 -+- now you have v4.0 + your_changes + aufs4.0 in you my4.0 branch. -+- you may need to solve some conflicts between your_changes and -+ aufs4.0. in this case, git-rerere is recommended so that you can -+ solve the similar conflicts automatically when you upgrade to 4.1 or -+ later in the future. -+ -+o aufs4-standalone tree -+$ git clone git://github.com/sfjro/aufs4-standalone.git aufs4-standalone.git -+$ cd aufs4-standalone.git -+$ git checkout origin/aufs4.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/aufs4.0 -+ -+Note: The 4.x-rcN branch is to be used with `rc' kernel versions ONLY. -+The minor version number, 'x' in '4.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-4.10" and the "aufs4.10" branch -+does not exist in aufs-util repository, then "aufs4.9", "aufs4.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 aufs4-linux tree, -+- enable CONFIG_AUFS_FS. -+- set other aufs configurations if necessary. -+ -+For aufs4-standalone tree, -+There are several ways to build. -+ -+1. -+- apply ./aufs4-kbuild.patch to your kernel source files. -+- apply ./aufs4-base.patch too. -+- apply ./aufs4-mmap.patch too. -+- apply ./aufs4-standalone.patch too, if you have a plan to set -+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs4-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. -+ Note: Since linux-3.9, every filesystem module requires an alias -+ "fs-". You should make sure that "fs-aufs" is listed in your -+ modules.aliases file if you set CONFIG_AUFS_FS=m. -+- 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 ./aufs4-base.patch to your kernel source files. -+- apply ./aufs4-mmap.patch too. -+- apply ./aufs4-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". -+ Note: Since linux-3.9, every filesystem module requires an alias -+ "fs-". You should make sure that "fs-aufs" is listed in your -+ modules.aliases file. -+- 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 aufs4-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 aufs4-standalone.git. They are all -+optional. When you meet some problems, they will help you. -+- aufs4-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". -+- 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, 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). -+Tomasz Szewczyk made a donation (2016/4). -+James Burry made a donation (2016/12). -+ -+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 --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt -new file mode 100644 -index 0000000..988772e ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/01intro.txt -@@ -0,0 +1,170 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+Introduction -+---------------------------------------- -+ -+aufs [ei ju: 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. -+ -+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 --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt -new file mode 100644 -index 0000000..1d1ccde ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/02struct.txt -@@ -0,0 +1,258 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt -new file mode 100644 -index 0000000..5f0aca4 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/03atomic_open.txt -@@ -0,0 +1,85 @@ -+ -+# Copyright (C) 2015-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt -new file mode 100644 -index 0000000..8b8ac6e ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/03lookup.txt -@@ -0,0 +1,113 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt -new file mode 100644 -index 0000000..5604ff8 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/04branch.txt -@@ -0,0 +1,74 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt -new file mode 100644 -index 0000000..1578469 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt -@@ -0,0 +1,64 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt -new file mode 100644 -index 0000000..9216478 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06fhsm.txt -@@ -0,0 +1,120 @@ -+ -+# Copyright (C) 2011-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ -+ -+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 --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt -new file mode 100644 -index 0000000..8fe4b6c ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06mmap.txt -@@ -0,0 +1,72 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt -new file mode 100644 -index 0000000..37cdb4e ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/06xattr.txt -@@ -0,0 +1,96 @@ -+ -+# Copyright (C) 2014-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ -+ -+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 --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt -new file mode 100644 -index 0000000..cd4ee6b ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/07export.txt -@@ -0,0 +1,58 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt -new file mode 100644 -index 0000000..7e07e26 ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/08shwh.txt -@@ -0,0 +1,52 @@ -+ -+# Copyright (C) 2005-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt -new file mode 100644 -index 0000000..b7ba75d ---- /dev/null -+++ b/Documentation/filesystems/aufs/design/10dynop.txt -@@ -0,0 +1,47 @@ -+ -+# Copyright (C) 2010-2017 Junjiro R. Okajima -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+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 --git a/MAINTAINERS b/MAINTAINERS -index 7875f7b..6a5590c 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2033,6 +2033,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: linux-unionfs@vger.kernel.org -+L: aufs-users@lists.sourceforge.net (members only) -+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 - W: http://miguelojeda.es/auxdisplay.htm -diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index ab0b2dd..2abdba9 100644 ---- a/drivers/block/loop.c -+++ b/drivers/block/loop.c -@@ -712,6 +712,24 @@ static inline int is_loop_device(struct file *file) - return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; - } - -+/* -+ * 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 --git a/fs/Kconfig b/fs/Kconfig -index a5d2dc3..64ba8bb 100644 ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -222,6 +222,7 @@ source "fs/pstore/Kconfig" - source "fs/sysv/Kconfig" - source "fs/ufs/Kconfig" - source "fs/exofs/Kconfig" -+source "fs/aufs/Kconfig" - - endif # MISC_FILESYSTEMS - -diff --git a/fs/Makefile b/fs/Makefile -index 3b54070..77ed517 100644 ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -127,3 +127,4 @@ obj-y += exofs/ # Multiple modules - obj-$(CONFIG_CEPH_FS) += ceph/ - obj-$(CONFIG_PSTORE) += pstore/ - obj-$(CONFIG_EFIVAR_FS) += efivarfs/ -+obj-$(CONFIG_AUFS_FS) += aufs/ -diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig -new file mode 100644 -index 0000000..63560ce ---- /dev/null -+++ b/fs/aufs/Kconfig -@@ -0,0 +1,185 @@ -+config AUFS_FS -+ 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 -+ 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 -+ 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_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 --git a/fs/aufs/Makefile b/fs/aufs/Makefile -new file mode 100644 -index 0000000..c7a501e ---- /dev/null -+++ b/fs/aufs/Makefile -@@ -0,0 +1,44 @@ -+ -+include ${src}/magic.mk -+ifeq (${CONFIG_AUFS_FS},m) -+include ${src}/conf.mk -+endif -+-include ${src}/priv_def.mk -+ -+# cf. include/linux/kernel.h -+# enable pr_debug -+ccflags-y += -DDEBUG -+# sparse requires the full pathname -+ifdef M -+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h -+else -+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h -+endif -+ -+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_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 --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h -new file mode 100644 -index 0000000..7f5eb78 ---- /dev/null -+++ b/fs/aufs/aufs.h -@@ -0,0 +1,59 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 "dynop.h" -+#include "file.h" -+#include "fstype.h" -+#include "inode.h" -+#include "loop.h" -+#include "module.h" -+#include "opts.h" -+#include "rwsem.h" -+#include "spl.h" -+#include "super.h" -+#include "sysaufs.h" -+#include "vfsub.h" -+#include "whout.h" -+#include "wkq.h" -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_H__ */ -diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c -new file mode 100644 -index 0000000..16e1e35 ---- /dev/null -+++ b/fs/aufs/branch.c -@@ -0,0 +1,1411 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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); -+ -+ if (br->br_xino.xi_file) -+ fput(br->br_xino.xi_file); -+ mutex_destroy(&br->br_xino.xi_nondir_mtx); -+ -+ AuDebugOn(au_br_count(br)); -+ au_br_count_fin(br); -+ -+ 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_delayed_kfree(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 */ -+ lockdep_off(); -+ path_put(&br->br_path); -+ lockdep_on(); -+ if (wbr) -+ au_delayed_kfree(wbr); -+ au_delayed_kfree(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; -+ root = sb->s_root; -+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); -+ if (unlikely(!add_branch)) -+ goto out; -+ -+ err = au_hnotify_init_br(add_branch, perm); -+ if (unlikely(err)) -+ goto out_br; -+ -+ 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; -+ } -+ -+ 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: -+ if (add_branch->br_wbr) -+ au_delayed_kfree(add_branch->br_wbr); -+out_hnotify: -+ au_hnotify_fin_br(add_branch); -+out_br: -+ au_delayed_kfree(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 mutex *h_mtx; -+ 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_mtx = NULL; -+ bindex = au_br_index(sb, br->br_id); -+ if (0 <= bindex) { -+ hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT); -+ } else { -+ h_dentry = au_br_dentry(br); -+ h_mtx = &d_inode(h_dentry)->i_mutex; -+ mutex_lock_nested(h_mtx, 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_imtx_unlock(hdir); -+ else -+ mutex_unlock(h_mtx); -+ vfsub_mnt_drop_write(au_br_mnt(br)); -+ br->br_perm = old_perm; -+ -+ if (!err && wbr && !au_br_writable(new_perm)) { -+ au_delayed_kfree(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 inode *h_inode; -+ -+ err = 0; -+ mutex_init(&br->br_xino.xi_nondir_mtx); -+ br->br_perm = add->perm; -+ br->br_path = add->path; /* set first, path_get() later */ -+ spin_lock_init(&br->br_dykey_lock); -+ au_br_count_init(br); -+ atomic_set(&br->br_xino_running, 0); -+ br->br_id = au_new_br_id(sb); -+ AuDebugOn(br->br_id < 0); -+ -+ 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)) { -+ h_inode = d_inode(add->path.dentry); -+ err = au_xino_br(sb, br, h_inode->i_ino, -+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1); -+ if (unlikely(err)) { -+ AuDebugOn(br->br_xino.xi_file); -+ 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); -+ 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; -+ if (!remount) -+ au_br_do_add(sb, add_branch, add_bindex); -+ else { -+ sysaufs_brs_del(sb, add_bindex); -+ au_br_do_add(sb, add_branch, add_bindex); -+ sysaufs_brs_add(sb, add_bindex); -+ } -+ -+ 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)); -+ -+ /* -+ * this test/set prevents aufs from handling unnecesary notify events -+ * of xino files, in case of re-adding a writable branch which was -+ * once detached from aufs. -+ */ -+ if (au_xino_brid(sb) < 0 -+ && au_br_writable(add_branch->br_perm) -+ && !au_test_fs_bad_xino(h_dentry->d_sb) -+ && add_branch->br_xino.xi_file -+ && add_branch->br_xino.xi_file->f_path.dentry->d_parent == h_dentry) -+ au_xino_brid_set(sb, add_branch->br_id); -+ -+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 au_sphlhead *files; -+ struct au_finfo *finfo; -+ -+ n = 0; -+ p = a; -+ files = &au_sbi(sb)->si_files; -+ spin_lock(&files->spin); -+ hlist_for_each_entry(finfo, &files->head, 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); -+ } -+ } -+ spin_unlock(&files->spin); -+ -+ return n; -+} -+ -+static struct file **au_farray_alloc(struct super_block *sb, -+ unsigned long long *max) -+{ -+ *max = au_nfiles(sb); -+ 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(); -+ -+ 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)); -+ -+ br_id = br->br_id; -+ opened = au_br_count(br); -+ 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); -+ } -+ -+ if (!remount) -+ au_br_do_del(sb, bindex, br); -+ else { -+ sysaufs_brs_del(sb, bindex); -+ au_br_do_del(sb, bindex, br); -+ sysaufs_brs_add(sb, bindex); -+ } -+ -+ 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); -+ -+ if (au_xino_brid(sb) == br_id) -+ au_xino_brid_set(sb, -1); -+ 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) -+ err = !access_ok(VERIFY_WRITE, &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; -+ -+ 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) { -+ put_write_access(file_inode(hf)); -+ __mnt_drop_write(hf->f_path.mnt); -+ } -+ } -+ -+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_delayed_kfree(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_delayed_kfree(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: -+ if (bf) -+ au_delayed_kfree(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 --git a/fs/aufs/branch.h b/fs/aufs/branch.h -new file mode 100644 -index 0000000..13aa12e ---- /dev/null -+++ b/fs/aufs/branch.h -@@ -0,0 +1,309 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * branch filesystems and xino for them -+ */ -+ -+#ifndef __AUFS_BRANCH_H__ -+#define __AUFS_BRANCH_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "dynop.h" -+#include "rwsem.h" -+#include "super.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* a xino file */ -+struct au_xino_file { -+ struct file *xi_file; -+ struct mutex xi_nondir_mtx; -+ -+ /* todo: make xino files an array to support huge inode number */ -+ -+#ifdef CONFIG_DEBUG_FS -+ struct dentry *xi_dbgaufs; -+#endif -+}; -+ -+/* 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_file 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]; -+ struct percpu_counter br_count; -+ -+ struct au_wbr *br_wbr; -+ struct au_br_fhsm *br_fhsm; -+ -+ /* xino truncation */ -+ atomic_t br_xino_running; -+ -+#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 -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 void au_br_get(struct au_branch *br) -+{ -+ percpu_counter_inc(&br->br_count); -+} -+ -+static inline void au_br_put(struct au_branch *br) -+{ -+ percpu_counter_dec(&br->br_count); -+} -+ -+static inline s64 au_br_count(struct au_branch *br) -+{ -+ return percpu_counter_sum(&br->br_count); -+} -+ -+static inline void au_br_count_init(struct au_branch *br) -+{ -+ percpu_counter_init(&br->br_count, 0, GFP_NOFS); -+} -+ -+static inline void au_br_count_fin(struct au_branch *br) -+{ -+ percpu_counter_destroy(&br->br_count); -+} -+ -+static inline int au_br_rdonly(struct au_branch *br) -+{ -+ return ((au_br_sb(br)->s_flags & MS_RDONLY) -+ || !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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* 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; -+ -+int au_xib_trunc(struct super_block *sb); -+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); -+struct file *au_xino_create2(struct file *base_file, struct file *copy_src); -+struct file *au_xino_create(struct super_block *sb, char *fname, int silent); -+ino_t au_xino_new_ino(struct super_block *sb); -+void au_xino_delete_inode(struct inode *inode, const int unlinked); -+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t ino); -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino); -+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino, -+ struct file *base_file, int do_test); -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex); -+ -+struct au_opt_xino; -+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount); -+void au_xino_clr(struct super_block *sb); -+struct file *au_xino_def(struct super_block *sb); -+int au_xino_path(struct seq_file *seq, struct file *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 void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ au_br_get(au_sbr(sb, bindex)); -+} -+ -+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ au_br_put(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)); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * wbr_wh_read_lock, wbr_wh_write_lock -+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock -+ */ -+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &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 --git a/fs/aufs/conf.mk b/fs/aufs/conf.mk -new file mode 100644 -index 0000000..0bbb2d3 ---- /dev/null -+++ b/fs/aufs/conf.mk -@@ -0,0 +1,38 @@ -+ -+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS} -+ -+define AuConf -+ifdef ${1} -+AuConfStr += ${1}=${${1}} -+endif -+endef -+ -+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \ -+ SBILIST \ -+ HNOTIFY HFSNOTIFY \ -+ EXPORT INO_T_64 \ -+ XATTR \ -+ FHSM \ -+ RDU \ -+ SHWH \ -+ BR_RAMFS \ -+ BR_FUSE POLL \ -+ BR_HFSPLUS \ -+ BDEV_LOOP \ -+ DEBUG MAGIC_SYSRQ -+$(foreach i, ${AuConfAll}, \ -+ $(eval $(call AuConf,CONFIG_AUFS_${i}))) -+ -+AuConfName = ${obj}/conf.str -+${AuConfName}.tmp: FORCE -+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@ -+${AuConfName}: ${AuConfName}.tmp -+ @diff -q $< $@ > /dev/null 2>&1 || { \ -+ echo ' GEN ' $@; \ -+ cp -p $< $@; \ -+ } -+FORCE: -+clean-files += ${AuConfName} ${AuConfName}.tmp -+${obj}/sysfs.o: ${AuConfName} -+ -+-include ${srctree}/${src}/conf_priv.mk -diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c -new file mode 100644 -index 0000000..9109020 ---- /dev/null -+++ b/fs/aufs/cpup.c -@@ -0,0 +1,1383 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 mutex *h_mtx; -+ /* 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_mtx = &file_inode(dst)->i_mutex; -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); -+ /* no delegation since it is just created */ -+ err = vfsub_notify_change(&dst->f_path, ia, -+ /*delegated*/NULL); -+ mutex_unlock(h_mtx); -+ } -+ } -+ -+ 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; -+ -+ err = -ENOMEM; -+ blksize = dst->f_path.dentry->d_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) -+ au_delayed_kfree(buf); -+ else -+ au_delayed_free_page((unsigned long)buf); -+ -+out: -+ 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; -+ void *label; -+ } *f, file[] = { -+ { -+ .bindex = cpg->bsrc, -+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, -+ .label = &&out -+ }, -+ { -+ .bindex = cpg->bdst, -+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, -+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), -+ .label = &&out_src -+ } -+ }; -+ struct super_block *sb; -+ 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); -+ err = PTR_ERR(f->file); -+ if (IS_ERR(f->file)) -+ goto *f->label; -+ } -+ -+ /* try stopping to update while we copyup */ -+ IMustLock(d_inode(file[SRC].dentry)); -+ err = au_copy_file(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 { -+ WARN(1, "%pD\nPlease report this warning to aufs-users ML", -+ file[DST].file); -+ 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(); -+ } -+ au_sbr_put(sb, file[DST].bindex); -+ -+out_src: -+ fput(file[SRC].file); -+ au_sbr_put(sb, file[SRC].bindex); -+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 */ -+ mutex_lock_nested(&h_src_inode->i_mutex, 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 = vfs_getattr(&h_path, &h_src_attr->st); -+ else { -+ mutex_unlock(&h_src_inode->i_mutex); -+ err = vfs_getattr(&h_path, &h_src_attr->st); -+ mutex_lock_nested(&h_src_inode->i_mutex, AuLsc_I_CHILD); -+ } -+ if (unlikely(err)) { -+ mutex_unlock(&h_src_inode->i_mutex); -+ goto out; -+ } -+ h_src_attr->valid = 1; -+ err = au_cp_regular(cpg); -+ mutex_unlock(&h_src_inode->i_mutex); -+ 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; -+ struct inode *h_inode = d_inode(h_src); -+ const struct inode_operations *h_iop = h_inode->i_op; -+ -+ err = -ENOSYS; -+ if (unlikely(!h_iop->readlink)) -+ goto out; -+ -+ 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 = h_iop->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); -+ } -+ au_delayed_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, -+ * particularry 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, S_IRUSR | S_IWUSR, -+ /*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); -+ 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. -+ */ -+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 reuduce 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); -+ mutex_lock_nested(&dst_inode->i_mutex, 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 */ -+ mutex_unlock(&dst_inode->i_mutex); -+ 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); */ -+ mutex_unlock(&dst_inode->i_mutex); -+ 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); */ -+ mutex_unlock(&dst_inode->i_mutex); -+ 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_delayed_kfree(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); -+ -+ mutex_lock_nested(&h_tmpdir->i_mutex, 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) { -+ mutex_unlock(&h_tmpdir->i_mutex); -+ /* 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 --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h -new file mode 100644 -index 0000000..9c20116 ---- /dev/null -+++ b/fs/aufs/cpup.h -@@ -0,0 +1,94 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 */ -+ -+#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 timespec 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 --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c -new file mode 100644 -index 0000000..ace36ed ---- /dev/null -+++ b/fs/aufs/dbgaufs.c -@@ -0,0 +1,438 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 = S_IRUSR | S_IRGRP | S_IROTH; -+ -+/* 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) -+{ -+ au_delayed_kfree(file->private_data); -+ return 0; -+} -+ -+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt) -+{ -+ 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 = vfs_getattr(&xf->f_path, &st); -+ if (!err) { -+ if (do_fcnt) -+ p->n = snprintf -+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n", -+ (long)file_count(xf), st.blocks, st.blksize, -+ (long long)st.size); -+ else -+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %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) -+{ -+ au_delayed_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 au_sphlhead *sphl; -+ -+ 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, sphl = sbinfo->si_plink; -+ i < AuPlink_NHASH; -+ i++, sphl++) { -+ n = au_sphl_count(sphl); -+ 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: -+ au_delayed_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); -+ 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; -+ long l; -+ struct au_sbinfo *sbinfo; -+ struct super_block *sb; -+ struct file *xf; -+ struct qstr *name; -+ -+ err = -ENOENT; -+ xf = NULL; -+ 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; -+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); -+ if (unlikely(err)) -+ goto out; -+ -+ sbinfo = inode->i_private; -+ sb = sbinfo->si_sb; -+ si_noflush_read_lock(sb); -+ if (l <= au_sbbot(sb)) { -+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file; -+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1); -+ } else -+ err = -ENOENT; -+ si_read_unlock(sb); -+ -+out: -+ 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_brs_del(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ aufs_bindex_t bbot; -+ struct au_branch *br; -+ struct au_xino_file *xi; -+ -+ if (!au_sbi(sb)->si_dbgaufs) -+ return; -+ -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ br = au_sbr(sb, bindex); -+ xi = &br->br_xino; -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ debugfs_remove(xi->xi_dbgaufs); -+ lockdep_on(); -+ xi->xi_dbgaufs = NULL; -+ } -+} -+ -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ struct au_sbinfo *sbinfo; -+ struct dentry *parent; -+ struct au_branch *br; -+ struct au_xino_file *xi; -+ aufs_bindex_t bbot; -+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */ -+ -+ sbinfo = au_sbi(sb); -+ parent = sbinfo->si_dbgaufs; -+ if (!parent) -+ return; -+ -+ bbot = au_sbbot(sb); -+ for (; bindex <= bbot; bindex++) { -+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); -+ br = au_sbr(sb, bindex); -+ xi = &br->br_xino; -+ AuDebugOn(xi->xi_dbgaufs); -+ /* debugfs acquires the parent i_mutex */ -+ lockdep_off(); -+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, -+ sbinfo, &dbgaufs_xino_fop); -+ lockdep_on(); -+ /* ignore an error */ -+ if (unlikely(!xi->xi_dbgaufs)) -+ AuWarn1("failed %s under debugfs\n", name); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#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); -+ 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; -+ kobject_put(&sbinfo->si_kobj); -+} -+ -+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; -+ kobject_get(&sbinfo->si_kobj); -+ -+ 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; -+ -+ 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; -+ -+ err = dbgaufs_xigen_init(sbinfo); -+ if (!err) -+ goto out; /* success */ -+ -+out_dir: -+ dbgaufs_si_fin(sbinfo); -+out: -+ 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 --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h -new file mode 100644 -index 0000000..d0c01c8 ---- /dev/null -+++ b/fs/aufs/dbgaufs.h -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * debugfs interface -+ */ -+ -+#ifndef __DBGAUFS_H__ -+#define __DBGAUFS_H__ -+ -+#ifdef __KERNEL__ -+ -+struct super_block; -+struct au_sbinfo; -+ -+#ifdef CONFIG_DEBUG_FS -+/* dbgaufs.c */ -+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); -+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); -+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_brs_del, struct super_block *sb, aufs_bindex_t bindex) -+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) -+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 --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c -new file mode 100644 -index 0000000..63516a1 ---- /dev/null -+++ b/fs/aufs/dcsub.c -@@ -0,0 +1,225 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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++); -+ au_delayed_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_delayed_kfree(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_delayed_kfree(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 *), -+ void (*finish)(void *)); -+ -+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, NULL); -+ -+ 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 --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h -new file mode 100644 -index 0000000..92d6f91 ---- /dev/null -+++ b/fs/aufs/dcsub.h -@@ -0,0 +1,136 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 --git a/fs/aufs/debug.c b/fs/aufs/debug.c -new file mode 100644 -index 0000000..0529b3f ---- /dev/null -+++ b/fs/aufs/debug.c -@@ -0,0 +1,440 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * debug print functions -+ */ -+ -+#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, S_IRUGO | S_IWUSR | S_IWGRP); -+ -+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 %lu\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)timespec_to_ns(&inode->i_ctime) & 0x0ffff, -+ inode->i_mapping ? inode->i_mapping->nrpages : 0, -+ inode->i_state, inode->i_flags, inode->i_version, -+ 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, cnt %lld, wbr %p}, " -+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " -+ "xino %d\n", -+ bindex, br->br_perm, br->br_id, au_br_count(br), -+ 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), !!br->br_xino.xi_file); -+ 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 reuduce 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; -+ au_br_count_init(&a->fake); -+ err = do_pri_br(-1, &a->fake); -+ au_br_count_fin(&a->fake); -+ au_delayed_kfree(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, -+ atomic_read(&sbinfo->si_kobj.kref.refcount)); -+ 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 --git a/fs/aufs/debug.h b/fs/aufs/debug.h -new file mode 100644 -index 0000000..270628d ---- /dev/null -+++ b/fs/aufs/debug.h -@@ -0,0 +1,225 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c -new file mode 100644 -index 0000000..d05c67b ---- /dev/null -+++ b/fs/aufs/dentry.c -@@ -0,0 +1,1130 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#include -+#include "aufs.h" -+ -+struct au_do_lookup_args { -+ unsigned int flags; -+ mode_t type; -+}; -+ -+/* -+ * 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 qstr *wh_name, -+ 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, wh_name, 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(&dentry->d_name, h_parent); -+ else -+ h_dentry = au_sio_lkup_one(&dentry->d_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; -+ -+ 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 */ -+ -+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); -+ opq = au_diropq_test(h_dentry); -+ mutex_unlock(&h_inode->i_mutex); -+ 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; -+ struct qstr whname; -+ struct au_do_lookup_args args = { -+ .flags = flags -+ }; -+ const struct qstr *name = &dentry->d_name; -+ struct dentry *parent; -+ struct super_block *sb; -+ -+ sb = dentry->d_sb; -+ err = au_test_shwh(sb, name); -+ if (unlikely(err)) -+ goto out; -+ -+ err = au_wh_name_alloc(&whname, name); -+ if (unlikely(err)) -+ goto out; -+ -+ isdir = !!d_is_dir(dentry); -+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); -+ -+ 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; -+ -+ 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; -+ -+ h_dir = d_inode(h_parent); -+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); -+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname, -+ &args); -+ mutex_unlock(&h_dir->i_mutex); -+ 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; -+ } -+ } -+ -+ 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_delayed_kfree(whname.name); -+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 = h_inode->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_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) -+ || ia->i_version != h_inode->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("nagative 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 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 -+ && !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; -+ 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; -+ } -+ } -+ } -+ -+ err = h_d_revalidate(dentry, inode, flags, do_udba); -+ 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 --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h -new file mode 100644 -index 0000000..d9dc991 ---- /dev/null -+++ b/fs/aufs/dentry.h -@@ -0,0 +1,255 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * lookup and dentry operations -+ */ -+ -+#ifndef __AUFS_DENTRY_H__ -+#define __AUFS_DENTRY_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#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 */ -+ union { -+ struct au_hdentry *di_hdentry; -+ struct llist_node di_lnode; /* delayed free */ -+ }; -+} ____cacheline_aligned_in_smp; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* flags for au_lkup_dentry() */ -+#define AuLkup_ALLOW_NEG 1 -+#define AuLkup_IGNORE_PERM (1 << 1) -+#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) -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* 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 --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c -new file mode 100644 -index 0000000..a092544 ---- /dev/null -+++ b/fs/aufs/dinfo.c -@@ -0,0 +1,553 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_dfree_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_delayed_kfree(dinfo->di_hdentry); -+ au_cache_dfree_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)) { -+ di_write_lock_child(d1); -+ di_write_lock_child2(d2); -+ } else { -+ /* there should be no races */ -+ 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)) { -+ di_write_lock_parent(d1); -+ di_write_lock_parent2(d2); -+ } else { -+ /* there should be no races */ -+ 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 --git a/fs/aufs/dir.c b/fs/aufs/dir.c -new file mode 100644 -index 0000000..388f838 ---- /dev/null -+++ b/fs/aufs/dir.c -@@ -0,0 +1,764 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * directory operations -+ */ -+ -+#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_imtx_lock_nested(hdir, AuLsc_I_PARENT); -+ h_dir = au_h_iptr(dir, btop); -+ if (h_dir->i_nlink -+ && timespec_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { -+ dt.dt_h_path = h_path; -+ au_dtime_revert(&dt); -+ } -+ au_hn_imtx_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_delayed_kfree(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_delayed_kfree(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 = d_inode(dentry)->i_version; -+ 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_delayed_kfree(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; -+ int execed, delayed; -+ -+ delayed = (current->flags & PF_KTHREAD) || in_interrupt(); -+ finfo = au_fi(file); -+ fidir = finfo->fi_hdir; -+ if (fidir) { -+ au_sphl_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, delayed); -+ -+ bindex = finfo->fi_btop; -+ if (bindex >= 0) { -+ execed = vfsub_file_execed(file); -+ 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); -+ } -+ au_delayed_kfree(fidir); -+ finfo->fi_hdir = NULL; -+ } -+ au_finfo_fin(file, delayed); -+ 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); -+ 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; -+ struct mutex *mtx; -+ -+ err = 0; -+ dentry = file->f_path.dentry; -+ inode = d_inode(dentry); -+ mtx = &inode->i_mutex; -+ mutex_lock(mtx); -+ 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); -+ mutex_unlock(mtx); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int aufs_iterate(struct file *file, struct dir_context *ctx) -+{ -+ int err; -+ struct dentry *dentry; -+ struct inode *inode, *h_inode; -+ struct super_block *sb; -+ -+ AuDbg("%pD, ctx{%pf, %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); -+ 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; -+ -+ 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); -+ au_sbr_put(dentry->d_sb, arg->bindex); -+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? */ -+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); -+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); -+ mutex_unlock(&h_inode->i_mutex); -+ 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 = aufs_iterate, -+ .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 --git a/fs/aufs/dir.h b/fs/aufs/dir.h -new file mode 100644 -index 0000000..5ff6c17 ---- /dev/null -+++ b/fs/aufs/dir.h -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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; -+ union { -+ struct au_vdir_destr *str; -+ struct llist_node lnode; /* delayed free */ -+ }; -+} ____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; -+ -+ unsigned long vd_version; -+ unsigned int vd_deblk_sz; -+ union { -+ unsigned long vd_jiffy; -+ struct llist_node vd_lnode; /* delayed free */ -+ }; -+} ____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 atonce); -+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 --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c -new file mode 100644 -index 0000000..0344ca6 ---- /dev/null -+++ b/fs/aufs/dynop.c -@@ -0,0 +1,369 @@ -+/* -+ * Copyright (C) 2010-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 au_sphlhead dynop[AuDyLast]; -+ -+static struct au_dykey *dy_gfind_get(struct au_sphlhead *sphl, const void *h_op) -+{ -+ struct au_dykey *key, *tmp; -+ struct hlist_head *head; -+ -+ key = NULL; -+ head = &sphl->head; -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(tmp, head, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ key = tmp; -+ kref_get(&key->dk_kref); -+ break; -+ } -+ rcu_read_unlock(); -+ -+ 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 au_sphlhead *sphl, struct au_dykey *key) -+{ -+ struct au_dykey *tmp, *found; -+ struct hlist_head *head; -+ const void *h_op = key->dk_op.dy_hop; -+ -+ found = NULL; -+ head = &sphl->head; -+ spin_lock(&sphl->spin); -+ hlist_for_each_entry(tmp, head, dk_hnode) -+ if (tmp->dk_op.dy_hop == h_op) { -+ kref_get(&tmp->dk_kref); -+ found = tmp; -+ break; -+ } -+ if (!found) -+ hlist_add_head_rcu(&key->dk_hnode, head); -+ spin_unlock(&sphl->spin); -+ -+ 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); /* not delayed */ -+} -+ -+static void dy_free(struct kref *kref) -+{ -+ struct au_dykey *key; -+ struct au_sphlhead *sphl; -+ -+ key = container_of(kref, struct au_dykey, dk_kref); -+ sphl = dynop + key->dk_op.dy_type; -+ au_sphl_del_rcu(&key->dk_hnode, sphl); -+ 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(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 au_sphlhead *sphl; -+ 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; -+ -+ sphl = dynop + op->dy_type; -+ key = dy_gfind_get(sphl, 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(sphl, key); -+ if (old) { -+ au_delayed_kfree(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 defaut 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 au_sphlhead *sphl; -+ struct hlist_head *head; -+ struct au_dykey *key; -+ -+ sphl = dynop + AuDy_AOP; -+ head = &sphl->head; -+ spin_lock(&sphl->spin); -+ hlist_for_each_entry(key, head, dk_hnode) -+ dy_adx((void *)key, do_dx); -+ spin_unlock(&sphl->spin); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+void __init au_dy_init(void) -+{ -+ int i; -+ -+ /* make sure that 'struct au_dykey *' can be any type */ -+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key)); -+ -+ for (i = 0; i < AuDyLast; i++) -+ au_sphl_init(dynop + i); -+} -+ -+void au_dy_fin(void) -+{ -+ int i; -+ -+ for (i = 0; i < AuDyLast; i++) -+ WARN_ON(!hlist_empty(&dynop[i].head)); -+} -diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h -new file mode 100644 -index 0000000..c19c675 ---- /dev/null -+++ b/fs/aufs/dynop.h -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (C) 2010-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_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 */ -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* 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 --git a/fs/aufs/export.c b/fs/aufs/export.c -new file mode 100644 -index 0000000..b780e96 ---- /dev/null -+++ b/fs/aufs/export.c -@@ -0,0 +1,838 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 file *base) -+{ -+ int err; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(base, 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: -+ 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); -+ mutex_lock(&dir->i_mutex); -+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen); -+ mutex_unlock(&dir->i_mutex); -+ 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: -+ au_delayed_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: -+ au_delayed_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_br_get(br); -+ 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_br_put(br); -+ 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 --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c -new file mode 100644 -index 0000000..4fbe2fe ---- /dev/null -+++ b/fs/aufs/f_op.c -@@ -0,0 +1,774 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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); -+ } 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; -+ get_file(h_file); -+ } -+ if (IS_ERR(h_file)) -+ err = PTR_ERR(h_file); -+ else { -+ 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; -+ int delayed; -+ -+ finfo = au_fi(file); -+ au_sphl_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); -+ -+ delayed = (current->flags & PF_KTHREAD) || in_interrupt(); -+ au_finfo_fin(file, delayed); -+ 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-mamagement (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) -+{ -+ struct file *h_file; -+ int err; -+ -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); -+ 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 { -+ 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; -+ struct au_pin pin; -+ -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); -+ 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); -+ fput(h_file); -+ -+ /* 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); -+} -+ -+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); -+ 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) { -+ mutex_lock(&inode->i_mutex); -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) -+ break; -+ mutex_unlock(&inode->i_mutex); -+ 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); -+ -+ 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); -+ mutex_unlock(&inode->i_mutex); -+ 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); -+ 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); -+ -+ 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); -+ mutex_unlock(&inode->i_mutex); -+ 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); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); -+ /* todo: necessasry? */ -+ /* 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); -+ -+ 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); -+ mutex_unlock(&inode->i_mutex); -+ 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); -+ -+ 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); -+ mutex_unlock(&inode->i_mutex); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * 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 definitly bad, but is not a problem since "si_rwsem for -+ * read" allows muliple 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 = h_file->f_op->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); -+ -+ 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); -+ mutex_unlock(&inode->i_mutex); -+out: -+ return err; -+} -+ -+/* no one supports this operation, currently */ -+#if 0 -+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync) -+{ -+ int err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *file, *h_file; -+ -+ err = 0; /* -EBADF; */ /* posix? */ -+ if (unlikely(!(file->f_mode & FMODE_WRITE))) -+ goto out; -+ -+ file = kio->ki_filp; -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out_unlock; -+ -+ err = -ENOSYS; -+ h_file = au_hf_top(file); -+ if (h_file->f_op->aio_fsync) { -+ struct mutex *h_mtx; -+ -+ h_mtx = &file_inode(h_file)->i_mutex; -+ if (!is_sync_kiocb(kio)) { -+ get_file(h_file); -+ fput(file); -+ } -+ kio->ki_filp = h_file; -+ err = h_file->f_op->aio_fsync(kio, datasync); -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD); -+ if (!err) -+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); -+ /*ignore*/ -+ mutex_unlock(h_mtx); -+ } -+ au_write_post(inode, h_file, &wpre, /*written*/0); -+ -+out_unlock: -+ si_read_unlock(inode->sb); -+ mutex_unlock(&inode->i_mutex); -+out: -+ return err; -+} -+#endif -+ -+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); -+ 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); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ arg |= vfsub_file_flags(file) & FASYNC; /* stop calling h_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, -+ /* .aio_fsync = aufs_aio_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 -+}; -diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c -new file mode 100644 -index 0000000..ef6f99e ---- /dev/null -+++ b/fs/aufs/fhsm.c -@@ -0,0 +1,426 @@ -+/* -+ * Copyright (C) 2011-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+/* -+ * 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 unsigned int au_fhsm_poll(struct file *file, -+ struct poll_table_struct *wait) -+{ -+ unsigned int 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 = POLLIN /* | POLLRDNORM */; -+ -+ AuTraceErr((int)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 reglardless '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 --git a/fs/aufs/file.c b/fs/aufs/file.c -new file mode 100644 -index 0000000..eb5e91d ---- /dev/null -+++ b/fs/aufs/file.c -@@ -0,0 +1,852 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_br_get(br); -+ 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_br_put(br); -+out: -+ return h_file; -+} -+ -+static int au_cmoo(struct dentry *dentry) -+{ -+ int err, cmoo; -+ 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); -+ if (pid -+ && (current->pid == pid -+ || current->real_parent->pid == pid)) -+ 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, no_lock = args->no_lock; -+ struct dentry *dentry; -+ struct au_finfo *finfo; -+ -+ if (!no_lock) -+ 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)); -+ if (!no_lock) { -+ di_write_lock_child(dentry); -+ err = au_cmoo(dentry); -+ di_downgrade_lock(dentry, AuLock_IR); -+ if (!err) -+ err = args->open(file, vfsub_file_flags(file), NULL); -+ di_read_unlock(dentry, AuLock_IR); -+ } else { -+ err = au_cmoo(dentry); -+ if (!err) -+ err = args->open(file, vfsub_file_flags(file), -+ args->h_file); -+ if (!err && au_fbtop(file) != au_dbtop(dentry)) -+ /* -+ * cmoo happens after h_file was opened. -+ * need to refresh file later. -+ */ -+ atomic_dec(&au_fi(file)->fi_generation); -+ } -+ -+ finfo = au_fi(file); -+ if (!err) { -+ finfo->fi_file = file; -+ au_sphl_add(&finfo->fi_hlist, -+ &au_sbi(file->f_path.dentry->d_sb)->si_files); -+ } -+ if (!no_lock) -+ fi_write_unlock(file); -+ else { -+ lockdep_off(); -+ fi_write_unlock(file); -+ lockdep_on(); -+ } -+ if (unlikely(err)) { -+ finfo->fi_hdir = NULL; -+ au_finfo_fin(file, /*atonce*/0); -+ } -+ -+out: -+ return err; -+} -+ -+int au_reopen_nondir(struct file *file) -+{ -+ int err; -+ aufs_bindex_t btop; -+ struct dentry *dentry; -+ struct file *h_file, *h_file_tmp; -+ -+ dentry = file->f_path.dentry; -+ btop = au_dbtop(dentry); -+ 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_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) { -+ au_sbr_get(dentry->d_sb, btop); -+ 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); -+ 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) -+{ -+ int execed; -+ 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--; -+ } -+ } -+ -+ execed = vfsub_file_execed(file); -+ 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); -+ } -+ } 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); -+ 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); -+ } -+ 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) -+{ -+ 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(file); -+ figen = au_figen(file); -+ di_write_lock_child(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, -+ loff_t offset) -+{ 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 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, */ -+ .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 --git a/fs/aufs/file.h b/fs/aufs/file.h -new file mode 100644 -index 0000000..4fc7eca ---- /dev/null -+++ b/fs/aufs/file.h -@@ -0,0 +1,294 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * file operations -+ */ -+ -+#ifndef __AUFS_FILE_H__ -+#define __AUFS_FILE_H__ -+ -+#ifdef __KERNEL__ -+ -+#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_node fi_hlist; -+ union { -+ struct file *fi_file; /* very ugly */ -+ struct llist_node fi_lnode; /* delayed free */ -+ }; -+} ____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 no_lock; -+ 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); -+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 -+unsigned int aufs_poll(struct file *file, poll_table *wait); -+#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); -+ -+/* 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 atonce); -+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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * fi_read_lock, fi_write_lock, -+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock -+ */ -+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem); -+ -+#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 --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c -new file mode 100644 -index 0000000..5dfa1ed ---- /dev/null -+++ b/fs/aufs/finfo.c -@@ -0,0 +1,151 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_br_put(hf->hf_br); -+ 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, int atonce) -+{ -+ struct au_finfo *finfo; -+ -+ au_nfiles_dec(file->f_path.dentry->d_sb); -+ -+ finfo = au_fi(file); -+ AuDebugOn(finfo->fi_hdir); -+ AuRwDestroy(&finfo->fi_rwsem); -+ if (!atonce) -+ au_cache_dfree_finfo(finfo); -+ else -+ 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_nfiles_inc(dentry->d_sb); -+ 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 --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h -new file mode 100644 -index 0000000..4624f1e ---- /dev/null -+++ b/fs/aufs/fstype.h -@@ -0,0 +1,400 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 MS_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 --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c -new file mode 100644 -index 0000000..2647096 ---- /dev/null -+++ b/fs/aufs/hfsnotify.c -@@ -0,0 +1,287 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_dfree_hnotify(hn); -+ smp_mb__before_atomic(); -+ 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, au_hfsn_free_mark); -+ 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_mark(mark, br->br_hfsn->hfsn_group, hinode->hi_inode, -+ /*mnt*/NULL, /*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_delayed_kfree(hfsn); -+} -+ -+static int au_hfsn_handle_event(struct fsnotify_group *group, -+ struct inode *inode, -+ struct fsnotify_mark *inode_mark, -+ struct fsnotify_mark *vfsmount_mark, -+ u32 mask, void *data, int data_type, -+ const unsigned char *file_name, u32 cookie) -+{ -+ int err; -+ struct au_hnotify *hnotify; -+ struct inode *h_dir, *h_inode; -+ struct qstr h_child_qstr = QSTR_INIT(file_name, strlen(file_name)); -+ -+ 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 -+ -+ AuDebugOn(!inode_mark); -+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); -+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, 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 -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+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_delayed_kfree(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 --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c -new file mode 100644 -index 0000000..b5b6547 ---- /dev/null -+++ b/fs/aufs/hfsplus.c -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2010-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * special support for filesystems which aqucires an inode mutex -+ * at final closing a file, eg, hfsplus. -+ * -+ * This trick is very simple and stupid, just to open the file before really -+ * neceeary 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) -+{ -+ if (h_file) { -+ fput(h_file); -+ au_sbr_put(dentry->d_sb, bindex); -+ } -+} -diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c -new file mode 100644 -index 0000000..02a6c64 ---- /dev/null -+++ b/fs/aufs/hnotify.c -@@ -0,0 +1,723 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * abstraction to notify the direct changes on lower directories -+ */ -+ -+#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_dfree_hnotify(hn); -+ /* -+ * The upper dir was removed by udba, but the same named -+ * dir left. In this case, aufs assignes a new inode -+ * number and set the monitor again. -+ * For the lower dir, the old monitnor 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_dfree_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; -+ -+ /* mutex_lock_nested(&hi->i_mutex, 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); -+ /* mutex_unlock(&hi->i_mutex); */ -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+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) { -+ mutex_lock_nested(&a->h_inode->i_mutex, 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 */ -+ mutex_unlock(&a->h_inode->i_mutex); -+ } -+ -+ /* 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); */ -+ /* a->inode->i_version++; */ -+ } -+ -+ /* 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); -+ -+ 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_delayed_kfree(a); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, -+ 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 & FS_EVENTS_POSS_ON_CHILD) { -+ 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_delayed_kfree(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) -+{ -+ struct au_cache *cp; -+ -+ flush_delayed_work(&au_dfree.dwork); -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ AuDebugOn(!llist_empty(&cp->llist)); -+ kmem_cache_destroy(cp->cache); -+ cp->cache = NULL; -+} -+ -+AU_CACHE_DFREE_FUNC(hnotify, HNOTIFY, hn_lnode); -+ -+int __init au_hnotify_init(void) -+{ -+ int err; -+ struct au_cache *cp; -+ -+ err = -ENOMEM; -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ cp->cache = AuCache(au_hnotify); -+ if (cp->cache) { -+ 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) -+{ -+ struct au_cache *cp; -+ -+ if (au_hnotify_op.fin) -+ au_hnotify_op.fin(); -+ -+ /* cf. au_cache_fin() */ -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ if (cp->cache) -+ au_hn_destroy_cache(); -+} -diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c -new file mode 100644 -index 0000000..eb62950 ---- /dev/null -+++ b/fs/aufs/i_op.c -@@ -0,0 +1,1523 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * inode operations (except add/del/rename) -+ */ -+ -+#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 = -EACCES; -+ if ((write_mask && IS_IMMUTABLE(h_inode)) -+ || ((mask & MAY_EXEC) -+ && S_ISREG(h_inode->i_mode) -+ && (path_noexec(h_path) -+ || !(h_inode->i_mode & S_IXUGO)))) -+ 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 MS_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 %pf\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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct aopen_node { -+ struct hlist_node hlist; -+ struct file *file, *h_file; -+}; -+ -+static int au_do_aopen(struct inode *inode, struct file *file) -+{ -+ struct au_sphlhead *aopen; -+ struct aopen_node *node; -+ struct au_do_open_args args = { -+ .no_lock = 1, -+ .open = au_do_open_nondir -+ }; -+ -+ aopen = &au_sbi(inode->i_sb)->si_aopen; -+ spin_lock(&aopen->spin); -+ hlist_for_each_entry(node, &aopen->head, hlist) -+ if (node->file == file) { -+ args.h_file = node->h_file; -+ break; -+ } -+ spin_unlock(&aopen->spin); -+ /* AuDebugOn(!args.h_file); */ -+ -+ return au_do_open(file, &args); -+} -+ -+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct file *file, unsigned int open_flag, -+ umode_t create_mode, int *opened) -+{ -+ int err, h_opened = *opened; -+ unsigned int lkup_flags; -+ struct dentry *parent, *d; -+ struct au_sphlhead *aopen; -+ struct vfsub_aopen_args args = { -+ .open_flag = open_flag, -+ .create_mode = create_mode, -+ .opened = &h_opened -+ }; -+ 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)) -+ goto out_no_open; -+ -+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); -+ if (unlikely(err)) -+ goto out; -+ -+ 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)) -+ goto out_unlock; -+ -+ AuDbgDentry(dentry); -+ if (d_is_positive(dentry)) -+ goto out_unlock; -+ -+ args.file = get_empty_filp(); -+ err = PTR_ERR(args.file); -+ if (IS_ERR(args.file)) -+ goto out_unlock; -+ -+ args.file->f_flags = file->f_flags; -+ err = au_aopen_or_create(dir, dentry, &args); -+ AuTraceErr(err); -+ AuDbgFile(args.file); -+ if (unlikely(err < 0)) { -+ if (h_opened & FILE_OPENED) -+ fput(args.file); -+ else -+ put_filp(args.file); -+ goto out_unlock; -+ } -+ -+ /* some filesystems don't set FILE_CREATED while succeeded? */ -+ *opened |= FILE_CREATED; -+ if (h_opened & FILE_OPENED) -+ aopen_node.h_file = args.file; -+ else { -+ put_filp(args.file); -+ args.file = NULL; -+ } -+ aopen = &au_sbi(dir->i_sb)->si_aopen; -+ au_sphl_add(&aopen_node.hlist, aopen); -+ err = finish_open(file, dentry, au_do_aopen, opened); -+ au_sphl_del(&aopen_node.hlist, aopen); -+ AuTraceErr(err); -+ AuDbgFile(file); -+ if (aopen_node.h_file) -+ fput(aopen_node.h_file); -+ -+out_unlock: -+ di_write_unlock(parent); -+ aufs_read_unlock(dentry, AuLock_DW); -+ AuDbgDentry(dentry); -+ if (unlikely(err < 0)) -+ goto out; -+out_no_open: -+ if (err >= 0 && !(*opened & FILE_CREATED)) { -+ AuLabel(out_no_open); -+ dget(dentry); -+ err = finish_no_open(file, dentry); -+ } -+out: -+ AuDbg("%pd%s%s\n", dentry, -+ (*opened & FILE_CREATED) ? " created" : "", -+ (*opened & FILE_OPENED) ? " opened" : ""); -+ AuTraceErr(err); -+ 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); -+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); -+ err = au_lkup_neg(dentry, bcpup, /*wh*/0); -+ /* todo: no unlock here */ -+ mutex_unlock(&h_dir->i_mutex); -+ -+ 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_imtx_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_imtx_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; -+} -+ -+void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) -+{ -+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP) -+ p->hdir->hi_inode->i_mutex.owner = task; -+#endif -+} -+ -+void au_pin_hdir_acquire_nest(struct au_pin *p) -+{ -+ if (p->hdir) { -+ mutex_acquire_nest(&p->hdir->hi_inode->i_mutex.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); -+ mutex_release(&p->hdir->hi_inode->i_mutex.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)) { -+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); -+ if (ia->ia_size < i_size_read(a->h_inode)) -+ sz = ia->ia_size; -+ mutex_unlock(&a->h_inode->i_mutex); -+ } -+ -+ 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) -+ mutex_lock_nested(&a->h_inode->i_mutex, 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 = -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); -+ 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; -+ mutex_unlock(&a->h_inode->i_mutex); -+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); -+ mutex_lock_nested(&a->h_inode->i_mutex, 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: -+ mutex_unlock(&a->h_inode->i_mutex); -+ 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_delayed_kfree(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_srxattr(struct dentry *dentry, struct au_srxattr *arg) -+{ -+ int err; -+ struct path h_path; -+ struct super_block *sb; -+ struct au_icpup_args *a; -+ struct inode *inode, *h_inode; -+ -+ inode = d_inode(dentry); -+ 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; -+ -+ mutex_unlock(&a->h_inode->i_mutex); -+ switch (arg->type) { -+ case AU_XATTR_SET: -+ 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_XATTR_REMOVE: -+ err = vfsub_removexattr(h_path.dentry, arg->u.remove.name); -+ break; -+ case AU_ACL_SET: -+ err = -EOPNOTSUPP; -+ h_inode = d_inode(h_path.dentry); -+ if (h_inode->i_op->set_acl) -+ 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_delayed_kfree(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 aufs_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(struct vfsmount *mnt __maybe_unused, -+ struct dentry *dentry, struct kstat *st) -+{ -+ int err; -+ unsigned char positive; -+ struct path h_path; -+ struct inode *inode; -+ struct super_block *sb; -+ -+ 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) -+ err = vfs_getattr(&h_path, st); -+ 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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * Assumption: -+ * - the number of symlinks is not so many. -+ * -+ * Structure: -+ * - sbinfo (instead of iinfo) contains an hlist of struct au_symlink. -+ * If iinfo contained the hlist, then it would be rather large waste of memory -+ * I am afraid. -+ * - struct au_symlink contains the necessary info for h_inode follow_link() and -+ * put_link(). -+ */ -+ -+struct au_symlink { -+ union { -+ struct hlist_node hlist; -+ struct rcu_head rcu; -+ }; -+ -+ struct inode *h_inode; -+ void *h_cookie; -+}; -+ -+static void au_symlink_add(struct super_block *sb, struct au_symlink *slink, -+ struct inode *h_inode, void *cookie) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ ihold(h_inode); -+ slink->h_inode = h_inode; -+ slink->h_cookie = cookie; -+ sbinfo = au_sbi(sb); -+ au_sphl_add(&slink->hlist, &sbinfo->si_symlink); -+} -+ -+static void au_symlink_del(struct super_block *sb, struct au_symlink *slink) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ /* do not iput() within rcu */ -+ iput(slink->h_inode); -+ slink->h_inode = NULL; -+ sbinfo = au_sbi(sb); -+ au_sphl_del_rcu(&slink->hlist, &sbinfo->si_symlink); -+ kfree_rcu(slink, rcu); -+} -+ -+static const char *aufs_follow_link(struct dentry *dentry, void **cookie) -+{ -+ const char *ret; -+ struct inode *inode, *h_inode; -+ struct dentry *h_dentry; -+ struct au_symlink *slink; -+ int err; -+ aufs_bindex_t bindex; -+ -+ ret = NULL; /* suppress a warning */ -+ 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->follow_link)) -+ goto out_unlock; -+ -+ err = -ENOMEM; -+ slink = kmalloc(sizeof(*slink), GFP_NOFS); -+ if (unlikely(!slink)) -+ 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_free; -+ } -+ } -+ if (unlikely(!h_dentry)) -+ goto out_free; -+ -+ err = 0; -+ AuDbg("%pf\n", h_inode->i_op->follow_link); -+ AuDbgDentry(h_dentry); -+ ret = h_inode->i_op->follow_link(h_dentry, cookie); -+ dput(h_dentry); -+ -+ if (!IS_ERR_OR_NULL(ret)) { -+ au_symlink_add(inode->i_sb, slink, h_inode, *cookie); -+ *cookie = slink; -+ AuDbg("slink %p\n", slink); -+ goto out_unlock; /* success */ -+ } -+ -+out_free: -+ slink->h_inode = NULL; -+ kfree_rcu(slink, rcu); -+out_unlock: -+ aufs_read_unlock(dentry, AuLock_IR); -+out: -+ if (unlikely(err)) -+ ret = ERR_PTR(err); -+ AuTraceErrPtr(ret); -+ return ret; -+} -+ -+static void aufs_put_link(struct inode *inode, void *cookie) -+{ -+ struct au_symlink *slink; -+ struct inode *h_inode; -+ -+ slink = cookie; -+ AuDbg("slink %p\n", slink); -+ h_inode = slink->h_inode; -+ AuDbg("%pf\n", h_inode->i_op->put_link); -+ AuDbgInode(h_inode); -+ if (h_inode->i_op->put_link) -+ h_inode->i_op->put_link(h_inode, slink->h_cookie); -+ au_symlink_del(inode->i_sb, slink); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 timespec *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); -+ lockdep_on(); -+ -+ 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); -+ } -+ -+ lockdep_off(); -+ 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 -+ .setxattr = aufs_setxattr, -+ .getxattr = aufs_getxattr, -+ .listxattr = aufs_listxattr, -+ .removexattr = aufs_removexattr, -+#endif -+ -+ .readlink = generic_readlink, -+ .follow_link = aufs_follow_link, -+ .put_link = aufs_put_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 -+ .setxattr = aufs_setxattr, -+ .getxattr = aufs_getxattr, -+ .listxattr = aufs_listxattr, -+ .removexattr = aufs_removexattr, -+#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 -+ .setxattr = aufs_setxattr, -+ .getxattr = aufs_getxattr, -+ .listxattr = aufs_listxattr, -+ .removexattr = aufs_removexattr, -+#endif -+ -+ .update_time = aufs_update_time -+ } -+}; -diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c -new file mode 100644 -index 0000000..7d3ee91 ---- /dev/null -+++ b/fs/aufs/i_op_add.c -@@ -0,0 +1,924 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * inode operations (add entry) -+ */ -+ -+#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); -+ dir->i_version++; -+ 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 dentry *wh_dentry, *parent; -+ struct inode *h_dir; -+ struct super_block *sb; -+ struct au_branch *br; -+ /* to reuduce 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: -+ err = 0; -+ 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); -+ else -+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, -+ arg->u.c.aopen, br); -+ break; -+ case Symlink: -+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); -+ break; -+ case Mknod: -+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, -+ arg->u.m.dev); -+ break; -+ default: -+ BUG(); -+ } -+ created = !err; -+ if (!err) -+ err = epilog(dir, btop, wh_dentry, dentry); -+ -+ /* revert */ -+ if (unlikely(created && err && 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 (!err && try_aopen && !h_dir->i_op->atomic_open) -+ *arg->u.c.aopen->opened |= FILE_CREATED; -+ -+ 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_delayed_kfree(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 */ -+ mutex_lock(&dir->i_mutex); -+ -+ 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); -+ err = inode_permission(d_inode(h_parent), MAY_WRITE | MAY_EXEC); -+ if (unlikely(err)) -+ goto out_mnt; -+ -+ err = -ENOMEM; -+ h_dentry = d_alloc(h_parent, &dentry->d_name); -+ if (unlikely(!h_dentry)) -+ goto out_mnt; -+ -+ err = h_dir->i_op->tmpfile(h_dir, h_dentry, mode); -+ if (unlikely(err)) -+ goto out_dentry; -+ -+ 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); -+ } -+ -+out_dentry: -+ 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: -+ mutex_unlock(&dir->i_mutex); -+ 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; -+ } -+ -+ 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); -+ dir->i_version++; -+ 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_delayed_kfree(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 mutex *h_mtx; -+ 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_mtx = &d_inode(h_path.dentry)->i_mutex; -+ if (wh_dentry -+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD); -+ opq_dentry = au_diropq_create(dentry, bindex); -+ mutex_unlock(h_mtx); -+ 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); -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bindex); -+ mutex_unlock(h_mtx); -+ 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_delayed_kfree(a); -+out: -+ return err; -+} -diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c -new file mode 100644 -index 0000000..ae2c911 ---- /dev/null -+++ b/fs/aufs/i_op_del.c -@@ -0,0 +1,511 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * inode operations (del entry) -+ */ -+ -+#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 diciding 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); -+ dir->i_version++; -+} -+ -+/* -+ * 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 reuduce 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_delayed_kfree(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 reuduce 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_delayed_kfree(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c -new file mode 100644 -index 0000000..5984e3c ---- /dev/null -+++ b/fs/aufs/i_op_ren.c -@@ -0,0 +1,1015 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * inode operation (rename entry) -+ * todo: this is crazy monster -+ */ -+ -+#include "aufs.h" -+ -+enum { AuSRC, AuDST, AuSrcDst }; -+enum { AuPARENT, AuCHILD, AuParentChild }; -+ -+#define AuRen_ISDIR 1 -+#define AuRen_ISSAMEDIR (1 << 1) -+#define AuRen_WHSRC (1 << 2) -+#define AuRen_WHDST (1 << 3) -+#define AuRen_MNT_WRITE (1 << 4) -+#define AuRen_DT_DSTDIR (1 << 5) -+#define AuRen_DIROPQ (1 << 6) -+#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) -+ -+struct au_ren_args { -+ struct { -+ struct dentry *dentry, *h_dentry, *parent, *h_parent, -+ *wh_dentry; -+ struct inode *dir, *inode; -+ struct au_hinode *hdir; -+ struct au_dtime dt[AuParentChild]; -+ aufs_bindex_t btop; -+ } 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_h_dir sd[AuSRC].hdir->hi_inode -+#define src_dt sd[AuSRC].dt -+#define src_btop sd[AuSRC].btop -+ -+#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_h_dir sd[AuDST].hdir->hi_inode -+#define dst_dt sd[AuDST].dt -+#define dst_btop sd[AuDST].btop -+ -+ struct dentry *h_trap; -+ struct au_branch *br; -+ struct au_hinode *src_hinode; -+ struct path h_path; -+ struct au_nhash whlist; -+ aufs_bindex_t btgt, src_bwh, src_bdiropq; -+ -+ unsigned int flags; -+ -+ struct au_whtmp_rmdir *thargs; -+ struct dentry *h_dst; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * 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_rev_diropq(int err, struct au_ren_args *a) -+{ -+ int rerr; -+ -+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(a->src_dentry, a->btgt); -+ au_hn_imtx_unlock(a->src_hinode); -+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq); -+ if (rerr) -+ RevertFailure("remove diropq %pd", a->src_dentry); -+} -+ -+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); -+ 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); -+ 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; -+ if (au_ftest_ren(a->flags, DIROPQ) -+ && au_dbdiropq(d) == a->btgt) -+ au_fclr_ren(a->flags, DIROPQ); -+ 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); -+ 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_diropq(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *diropq; -+ -+ err = 0; -+ a->src_bdiropq = au_dbdiropq(a->src_dentry); -+ a->src_hinode = au_hi(a->src_inode, a->btgt); -+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD); -+ diropq = au_diropq_create(a->src_dentry, a->btgt); -+ au_hn_imtx_unlock(a->src_hinode); -+ if (IS_ERR(diropq)) -+ err = PTR_ERR(diropq); -+ else -+ dput(diropq); -+ -+ return err; -+} -+ -+static int do_rename(struct au_ren_args *a) -+{ -+ int err; -+ struct dentry *d, *h_d; -+ -+ /* prepare workqueue args for asynchronous rmdir */ -+ h_d = a->dst_h_dentry; -+ if (au_ftest_ren(a->flags, ISDIR) && 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->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->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); -+ -+ /* rename by vfs_rename or cpup */ -+ d = a->dst_dentry; -+ if (au_ftest_ren(a->flags, ISDIR) -+ && (a->dst_wh_dentry -+ || au_dbdiropq(d) == a->btgt -+ /* hide the lower to keep xino */ -+ || a->btgt < au_dbbot(d) -+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ))) -+ au_fset_ren(a->flags, DIROPQ); -+ err = au_ren_or_cpup(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_whtmp; -+ -+ /* make dir opaque */ -+ if (au_ftest_ren(a->flags, DIROPQ)) { -+ err = au_ren_diropq(a); -+ if (unlikely(err)) -+ goto out_rename; -+ } -+ -+ /* update target timestamps */ -+ 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; -+ -+ /* 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: -+ if (au_ftest_ren(a->flags, 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 @dentry dir can be rename source or not. -+ * if it can, return 0 and @children is filled. -+ * success means, -+ * - it is a logically empty dir. -+ * - or, it exists on writable branch and has no children including whiteouts -+ * on the lower branch. -+ */ -+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt) -+{ -+ int err; -+ unsigned int rdhash; -+ aufs_bindex_t btop; -+ -+ btop = au_dbtop(dentry); -+ if (btop != btgt) { -+ struct au_nhash whlist; -+ -+ 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; -+ 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) { -+ 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->flags, ISDIR) && 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; -+ -+ au_set_dbtop(d, a->dst_btop); -+ err = may_rename_dstdir(d, &a->whlist); -+ au_set_dbtop(d, a->btgt); -+ } -+ 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->flags, ISDIR)) { -+ err = may_rename_srcdir(d, a->btgt); -+ 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->flags, ISDIR)); -+ 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->flags, ISDIR); -+ 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 exitsts -+ * (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->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->flags, MNT_WRITE); -+ 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; -+ dir->i_version++; -+ if (au_ftest_ren(a->flags, ISDIR)) { -+ /* 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 (au_ftest_ren(a->flags, ISSAMEDIR)) -+ return; -+ -+ dir = a->src_dir; -+ dir->i_version++; -+ if (au_ftest_ren(a->flags, ISDIR)) -+ 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 (!au_ftest_ren(a->flags, ISDIR)) -+ vfsub_drop_nlink(i); -+ else { -+ vfsub_dead_dir(i); -+ au_cpup_attr_timesizes(i); -+ } -+ au_update_dbrange(d, /*do_put_zero*/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); -+ } -+ -+ 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->flags, ISDIR)) -+ 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; -+ -+ 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->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->flags, DT_DSTDIR); -+ if (!au_ftest_ren(a->flags, ISDIR)) -+ 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->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 mutex *h_mtx; -+ -+ au_dtime_revert(a->src_dt + AuPARENT); -+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) -+ au_dtime_revert(a->dst_dt + AuPARENT); -+ -+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) { -+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; -+ h_mtx = &d_inode(h_d)->i_mutex; -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD); -+ au_dtime_revert(a->src_dt + AuCHILD); -+ mutex_unlock(h_mtx); -+ -+ if (au_ftest_ren(a->flags, DT_DSTDIR)) { -+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; -+ h_mtx = &d_inode(h_d)->i_mutex; -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD); -+ au_dtime_revert(a->dst_dt + AuCHILD); -+ mutex_unlock(h_mtx); -+ } -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, -+ struct inode *_dst_dir, struct dentry *_dst_dentry) -+{ -+ int err, flags; -+ /* reduce stack space */ -+ struct au_ren_args *a; -+ -+ AuDbg("%pd, %pd\n", _src_dentry, _dst_dentry); -+ IMustLock(_src_dir); -+ IMustLock(_dst_dir); -+ -+ err = -ENOMEM; -+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); -+ a = kzalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ 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) { -+ IMustLock(a->dst_inode); -+ au_igrab(a->dst_inode); -+ } -+ -+ err = -ENOTDIR; -+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; -+ if (d_is_dir(a->src_dentry)) { -+ au_fset_ren(a->flags, ISDIR); -+ if (unlikely(d_really_is_positive(a->dst_dentry) -+ && !d_is_dir(a->dst_dentry))) -+ goto out_free; -+ flags |= AuLock_DIRS; -+ } -+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, 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 dst_dentry before this -+ * function. It means we cannot rely upon d_unhashed(). -+ */ -+ if (unlikely(!a->dst_inode->i_nlink)) -+ goto out_unlock; -+ if (!S_ISDIR(a->dst_inode->i_mode)) { -+ err = au_d_hashed_positive(a->dst_dentry); -+ if (unlikely(err)) -+ 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->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->flags, WHDST); -+ } else { -+ err = au_cpup_dirs(a->dst_dentry, a->btgt); -+ if (unlikely(err)) -+ goto out_children; -+ } -+ -+ 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->flags, ISDIR), -+ &a->btgt); -+ di_write_unlock(a->src_parent); -+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1); -+ au_fclr_ren(a->flags, ISSAMEDIR); -+ } else -+ err = au_wr_dir_need_wh(a->src_dentry, -+ au_ftest_ren(a->flags, ISDIR), -+ &a->btgt); -+ if (unlikely(err < 0)) -+ goto out_children; -+ if (err) -+ au_fset_ren(a->flags, WHSRC); -+ -+ /* cpup src */ -+ if (a->src_btop != a->btgt) { -+ struct au_pin pin; -+ -+ 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); -+ au_fset_ren(a->flags, WHSRC); -+ } -+ -+ /* lock them all */ -+ err = au_ren_lock(a); -+ if (unlikely(err)) -+ /* leave the copied-up one */ -+ goto out_children; -+ -+ 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); -+ -+ /* here we go */ -+ err = do_rename(a); -+ if (unlikely(err)) -+ goto out_dt; -+ -+ /* update dir attributes */ -+ au_ren_refresh_dir(a); -+ -+ /* dput/iput all lower dentries */ -+ au_ren_refresh(a); -+ -+ goto out_hdir; /* success */ -+ -+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) -+ d_move(a->src_dentry, a->dst_dentry); -+ else { -+ au_update_dbtop(a->dst_dentry); -+ if (!a->dst_inode) -+ d_drop(a->dst_dentry); -+ } -+ if (au_ftest_ren(a->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_delayed_kfree(a); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c -new file mode 100644 -index 0000000..ce9f157 ---- /dev/null -+++ b/fs/aufs/iinfo.c -@@ -0,0 +1,285 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_ninodes_inc(sb); -+ -+ 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_ninodes_dec(sb); -+ 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, /*atonce*/0); -+ -+ 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_delayed_kfree(iinfo->ii_hinode); -+ AuRwDestroy(&iinfo->ii_rwsem); -+} -diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c -new file mode 100644 -index 0000000..2cce490 ---- /dev/null -+++ b/fs/aufs/inode.c -@@ -0,0 +1,519 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * inode functions -+ */ -+ -+#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->i_version++; -+} -+ -+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; -+ struct mutex *mtx; -+ -+ /* prevent hardlinked inode number from race condition */ -+ mtx = NULL; -+ if (d_type != DT_DIR) { -+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx; -+ mutex_lock(mtx); -+ } -+ err = au_xino_read(sb, bindex, h_ino, ino); -+ if (unlikely(err)) -+ goto out; -+ -+ if (!*ino) { -+ err = -EIO; -+ *ino = au_xino_new_ino(sb); -+ if (unlikely(!*ino)) -+ goto out; -+ err = au_xino_write(sb, bindex, h_ino, *ino); -+ if (unlikely(err)) -+ goto out; -+ } -+ -+out: -+ if (mtx) -+ mutex_unlock(mtx); -+ 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; -+ struct mutex *mtx; -+ ino_t h_ino, ino; -+ int err; -+ 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; -+ -+ /* -+ * stop 'race'-ing between hardlinks under different -+ * parents. -+ */ -+ mtx = NULL; -+ if (!d_is_dir(h_dentry)) -+ mtx = &au_sbr(sb, btop)->br_xino.xi_nondir_mtx; -+ -+new_ino: -+ if (mtx) -+ mutex_lock(mtx); -+ err = au_xino_read(sb, btop, h_ino, &ino); -+ inode = ERR_PTR(err); -+ if (unlikely(err)) -+ goto out; -+ -+ if (!ino) { -+ ino = au_xino_new_ino(sb); -+ if (unlikely(!ino)) { -+ inode = ERR_PTR(-EIO); -+ goto out; -+ } -+ } -+ -+ AuDbg("i%lu\n", (unsigned long)ino); -+ inode = au_iget_locked(sb, ino); -+ err = PTR_ERR(inode); -+ if (IS_ERR(inode)) -+ goto out; -+ -+ 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; /* 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 (mtx) -+ mutex_unlock(mtx); -+ err = reval_inode(inode, dentry); -+ if (unlikely(err < 0)) { -+ mtx = NULL; -+ goto out_iput; -+ } -+ -+ if (!err) { -+ mtx = NULL; -+ goto out; /* success */ -+ } else if (mtx) -+ mutex_lock(mtx); -+ } -+ -+ 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 (mtx) -+ mutex_unlock(mtx); -+ goto new_ino; -+ } -+ -+out_iput: -+ iput(inode); -+ inode = ERR_PTR(err); -+out: -+ if (mtx) -+ mutex_unlock(mtx); -+ 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 --git a/fs/aufs/inode.h b/fs/aufs/inode.h -new file mode 100644 -index 0000000..b9545e4 ---- /dev/null -+++ b/fs/aufs/inode.h -@@ -0,0 +1,701 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 -+ union { -+ struct inode *hn_aufs_inode; /* no get/put */ -+ struct llist_node hn_lnode; /* delayed free */ -+ }; -+#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; -+ union { -+ struct hlist_node plink; -+ struct llist_node lnode; /* delayed free */ -+ }; -+} ____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_set_owner(struct au_pin *p, struct task_struct *task); -+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); -+ -+/* 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); -+ssize_t aufs_getxattr(struct dentry *dentry, const char *name, void *value, -+ size_t size); -+int aufs_setxattr(struct dentry *dentry, const char *name, const void *value, -+ size_t size, int flags); -+int aufs_removexattr(struct dentry *dentry, const char *name); -+ -+/* 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_XATTR_REMOVE, -+ AU_ACL_SET -+}; -+ -+struct au_srxattr { -+ int type; -+ union { -+ struct { -+ const char *name; -+ const void *value; -+ size_t size; -+ int flags; -+ } set; -+ struct { -+ const char *name; -+ } remove; -+ struct { -+ struct posix_acl *acl; -+ int type; -+ } acl_set; -+ } u; -+}; -+ssize_t au_srxattr(struct dentry *dentry, struct au_srxattr *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 -+ -+/* -+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock -+ */ -+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &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, -+ 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_imtx_lock(struct au_hinode *hdir) -+{ -+ mutex_lock(&hdir->hi_inode->i_mutex); -+ au_hn_suspend(hdir); -+} -+ -+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir, -+ unsigned int sc __maybe_unused) -+{ -+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc); -+ au_hn_suspend(hdir); -+} -+ -+static inline void au_hn_imtx_unlock(struct au_hinode *hdir) -+{ -+ au_hn_resume(hdir); -+ mutex_unlock(&hdir->hi_inode->i_mutex); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_INODE_H__ */ -diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c -new file mode 100644 -index 0000000..5e501c5 ---- /dev/null -+++ b/fs/aufs/ioctl.c -@@ -0,0 +1,219 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_br_put(br); /* 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 --git a/fs/aufs/loop.c b/fs/aufs/loop.c -new file mode 100644 -index 0000000..1b31f47 ---- /dev/null -+++ b/fs/aufs/loop.c -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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(unsigned long)); -+ -+ 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_delayed_kfree(au_warn_loopback_array); -+} -diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h -new file mode 100644 -index 0000000..9b02d32 ---- /dev/null -+++ b/fs/aufs/loop.h -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 -+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 --git a/fs/aufs/magic.mk b/fs/aufs/magic.mk -new file mode 100644 -index 0000000..4f83bdf ---- /dev/null -+++ b/fs/aufs/magic.mk -@@ -0,0 +1,30 @@ -+ -+# 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 --git a/fs/aufs/module.c b/fs/aufs/module.c -new file mode 100644 -index 0000000..e89e65d ---- /dev/null -+++ b/fs/aufs/module.c -@@ -0,0 +1,333 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_delayed_kfree(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_delayed_kfree(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 au_dfree au_dfree; -+ -+/* delayed free */ -+static void au_do_dfree(struct work_struct *work __maybe_unused) -+{ -+ struct llist_head *head; -+ struct llist_node *node, *next; -+ -+#define AU_CACHE_DFREE_DO_BODY(name, idx, lnode) do { \ -+ head = &au_dfree.cache[AuCache_##idx].llist; \ -+ node = llist_del_all(head); \ -+ for (; node; node = next) { \ -+ struct au_##name *p \ -+ = llist_entry(node, struct au_##name, \ -+ lnode); \ -+ next = llist_next(node); \ -+ au_cache_free_##name(p); \ -+ } \ -+ } while (0) -+ -+ AU_CACHE_DFREE_DO_BODY(dinfo, DINFO, di_lnode); -+ AU_CACHE_DFREE_DO_BODY(icntnr, ICNTNR, lnode); -+ AU_CACHE_DFREE_DO_BODY(finfo, FINFO, fi_lnode); -+ AU_CACHE_DFREE_DO_BODY(vdir, VDIR, vd_lnode); -+ AU_CACHE_DFREE_DO_BODY(vdir_dehstr, DEHSTR, lnode); -+#ifdef CONFIG_AUFS_HNOTIFY -+ AU_CACHE_DFREE_DO_BODY(hnotify, HNOTIFY, hn_lnode); -+#endif -+ -+#define AU_DFREE_DO_BODY(llist, func) do { \ -+ node = llist_del_all(llist); \ -+ for (; node; node = next) { \ -+ next = llist_next(node); \ -+ func(node); \ -+ } \ -+ } while (0) -+ -+ AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_KFREE, kfree); -+ AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_FREE_PAGE, au_free_page); -+ -+#undef AU_CACHE_DFREE_DO_BODY -+#undef AU_DFREE_DO_BODY -+} -+ -+AU_CACHE_DFREE_FUNC(dinfo, DINFO, di_lnode); -+AU_CACHE_DFREE_FUNC(icntnr, ICNTNR, lnode); -+AU_CACHE_DFREE_FUNC(finfo, FINFO, fi_lnode); -+AU_CACHE_DFREE_FUNC(vdir, VDIR, vd_lnode); -+AU_CACHE_DFREE_FUNC(vdir_dehstr, DEHSTR, lnode); -+ -+static void au_cache_fin(void) -+{ -+ int i; -+ struct au_cache *cp; -+ -+ /* -+ * 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); -+ flush_delayed_work(&au_dfree.dwork); -+ for (i = 0; i < AuCache_HNOTIFY; i++) { -+ cp = au_dfree.cache + i; -+ AuDebugOn(!llist_empty(&cp->llist)); -+ kmem_cache_destroy(cp->cache); -+ cp->cache = NULL; -+ } -+} -+ -+static int __init au_cache_init(void) -+{ -+ struct au_cache *cp; -+ -+ cp = au_dfree.cache; -+ cp[AuCache_DINFO].cache = AuCacheCtor(au_dinfo, au_di_init_once); -+ if (cp[AuCache_DINFO].cache) -+ /* SLAB_DESTROY_BY_RCU */ -+ cp[AuCache_ICNTNR].cache = AuCacheCtor(au_icntnr, -+ au_icntnr_init_once); -+ if (cp[AuCache_ICNTNR].cache) -+ cp[AuCache_FINFO].cache = AuCacheCtor(au_finfo, -+ au_fi_init_once); -+ if (cp[AuCache_FINFO].cache) -+ cp[AuCache_VDIR].cache = AuCache(au_vdir); -+ if (cp[AuCache_VDIR].cache) -+ cp[AuCache_DEHSTR].cache = AuCache(au_vdir_dehstr); -+ if (cp[AuCache_DEHSTR].cache) -+ 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 au_sphlhead 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); -+MODULE_ALIAS_FS(AUFS_NAME); -+ -+/* 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, S_IRUGO); -+ -+/* 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, S_IRUGO); -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 if (err < 0) -+ err = -ENOMEM; -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int __init aufs_init(void) -+{ -+ int err, i; -+ char *p; -+ struct au_cache *cp; -+ -+ 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; -+ -+ /* First, initialize au_dfree */ -+ for (i = 0; i < AuCache_Last; i++) { /* including hnotify */ -+ cp = au_dfree.cache + i; -+ cp->cache = NULL; -+ init_llist_head(&cp->llist); -+ } -+ for (i = 0; i < AU_DFREE_Last; i++) -+ init_llist_head(au_dfree.llist + i); -+ INIT_DELAYED_WORK(&au_dfree.dwork, au_do_dfree); -+ -+ au_sbilist_init(); -+ sysaufs_brs_init(); -+ au_debug_init(); -+ au_dy_init(); -+ err = sysaufs_init(); -+ if (unlikely(err)) -+ goto out; -+ err = au_procfs_init(); -+ if (unlikely(err)) -+ goto out_sysaufs; -+ 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_sysaufs: -+ sysaufs_fin(); -+ au_dy_fin(); -+ flush_delayed_work(&au_dfree.dwork); -+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(); -+ sysaufs_fin(); -+ au_dy_fin(); -+ flush_delayed_work(&au_dfree.dwork); -+} -+ -+module_init(aufs_init); -+module_exit(aufs_exit); -diff --git a/fs/aufs/module.h b/fs/aufs/module.h -new file mode 100644 -index 0000000..e0ade15 ---- /dev/null -+++ b/fs/aufs/module.h -@@ -0,0 +1,156 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * module initialization and module-global -+ */ -+ -+#ifndef __AUFS_MODULE_H__ -+#define __AUFS_MODULE_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include "debug.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); -+ -+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 and delayed free */ -+enum { -+ AuCache_DINFO, -+ AuCache_ICNTNR, -+ AuCache_FINFO, -+ AuCache_VDIR, -+ AuCache_DEHSTR, -+ AuCache_HNOTIFY, /* must be last */ -+ AuCache_Last -+}; -+ -+enum { -+ AU_DFREE_KFREE, -+ AU_DFREE_FREE_PAGE, -+ AU_DFREE_Last -+}; -+ -+struct au_cache { -+ struct kmem_cache *cache; -+ struct llist_head llist; /* delayed free */ -+}; -+ -+/* -+ * in order to reduce the cost of the internal timer, consolidate all the -+ * delayed free works into a single delayed_work. -+ */ -+struct au_dfree { -+ struct au_cache cache[AuCache_Last]; -+ struct llist_head llist[AU_DFREE_Last]; -+ struct delayed_work dwork; -+}; -+ -+extern struct au_dfree au_dfree; -+ -+#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 AU_DFREE_DELAY msecs_to_jiffies(10) -+#define AU_DFREE_BODY(lnode, llist) do { \ -+ if (llist_add(lnode, llist)) \ -+ schedule_delayed_work(&au_dfree.dwork, \ -+ AU_DFREE_DELAY); \ -+ } while (0) -+#define AU_CACHE_DFREE_FUNC(name, idx, lnode) \ -+ void au_cache_dfree_##name(struct au_##name *p) \ -+ { \ -+ struct au_cache *cp = au_dfree.cache + AuCache_##idx; \ -+ AU_DFREE_BODY(&p->lnode, &cp->llist); \ -+ } -+ -+#define AuCacheFuncs(name, index) \ -+static inline struct au_##name *au_cache_alloc_##name(void) \ -+{ return kmem_cache_alloc(au_dfree.cache[AuCache_##index].cache, GFP_NOFS); } \ -+static inline void au_cache_free_##name(struct au_##name *p) \ -+{ kmem_cache_free(au_dfree.cache[AuCache_##index].cache, p); } \ -+void au_cache_dfree_##name(struct au_##name *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 -+ -+static inline void au_delayed_kfree(const void *p) -+{ -+ AuDebugOn(!p); -+ AuDebugOn(ksize(p) < sizeof(struct llist_node)); -+ -+ AU_DFREE_BODY((void *)p, au_dfree.llist + AU_DFREE_KFREE); -+} -+ -+/* cast only */ -+static inline void au_free_page(void *p) -+{ -+ free_page((unsigned long)p); -+} -+ -+static inline void au_delayed_free_page(unsigned long addr) -+{ -+ AU_DFREE_BODY((void *)addr, au_dfree.llist + AU_DFREE_FREE_PAGE); -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_MODULE_H__ */ -diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c -new file mode 100644 -index 0000000..bf17fb3 ---- /dev/null -+++ b/fs/aufs/mvdown.c -@@ -0,0 +1,704 @@ -+/* -+ * Copyright (C) 2011-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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) -+ && (!(au_br_sb(br)->s_flags & MS_RDONLY))) -+ 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 (!(au_br_sb(br)->s_flags & MS_RDONLY)) { -+ 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) -+ err = !access_ok(VERIFY_WRITE, 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); -+ mutex_lock_nested(&args->dir->i_mutex, 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; -+ } -+ -+ mutex_lock_nested(&inode->i_mutex, 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: -+ mutex_unlock(&inode->i_mutex); -+out_dir: -+ mutex_unlock(&args->dir->i_mutex); -+out_free: -+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); -+ if (unlikely(e)) -+ err = -EFAULT; -+ au_delayed_kfree(args); -+out: -+ AuTraceErr(err); -+ return err; -+} -diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c -new file mode 100644 -index 0000000..544db8c ---- /dev/null -+++ b/fs/aufs/opts.c -@@ -0,0 +1,1870 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_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_FHSM -+ {Opt_fhsm_sec, "fhsm_sec=%d"}, -+#else -+ {Opt_ignore_silent, "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_silent, "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_silent, "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} -+}; -+ -+/* -+ * cf. linux/lib/parser.c and cmdline.c -+ * gave up calling memparse() since it uses simple_strtoull() instead of -+ * kstrto...(). -+ */ -+static int noinline_for_stack -+au_match_ull(substring_t *s, unsigned long long *result) -+{ -+ int err; -+ unsigned int len; -+ char a[32]; -+ -+ err = -ERANGE; -+ len = s->to - s->from; -+ if (len + 1 <= sizeof(a)) { -+ memcpy(a, s->from, len); -+ a[len] = '\0'; -+ err = kstrtoull(a, 0, result); -+ } -+ return err; -+} -+ -+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 (!au_match_ull(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_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 & MS_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 permssion %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); -+ 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_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_delayed_kfree(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); -+ 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); -+ 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_acl: -+ sb->s_flags |= MS_POSIXACL; -+ break; -+ case Opt_noacl: -+ sb->s_flags &= ~MS_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; -+ case Opt_prepend: -+ opt->add.bindex = 0; -+ 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; -+ aufs_bindex_t bbot, bindex; -+ struct dentry *root, *parent, *h_root; -+ -+ 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; -+ au_xino_brid_set(sb, -1); -+ -+ /* safe d_parent access */ -+ parent = opt->xino.file->f_path.dentry->d_parent; -+ root = sb->s_root; -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ h_root = au_h_dptr(root, bindex); -+ if (h_root == parent) { -+ au_xino_brid_set(sb, au_sbr_id(sb, bindex)); -+ break; -+ } -+ } -+ break; -+ -+ case Opt_noxino: -+ au_xino_clr(sb); -+ au_xino_brid_set(sb, -1); -+ *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 & MS_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 & MS_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_imtx_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_imtx_unlock(hdir); -+ -+ if (!err && do_free) { -+ if (wbr) -+ au_delayed_kfree(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 = 0; -+ 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); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+unsigned int au_opt_udba(struct super_block *sb) -+{ -+ return au_mntflags(sb) & AuOptMask_UDBA; -+} -diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h -new file mode 100644 -index 0000000..1cc990e ---- /dev/null -+++ b/fs/aufs/opts.h -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * mount options/flags -+ */ -+ -+#ifndef __AUFS_OPTS_H__ -+#define __AUFS_OPTS_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+ -+struct file; -+struct super_block; -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* 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) /* busy inode when del-branch */ -+#define AuOpt_DIO (1 << 14) /* direct io */ -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuOpt_UDBA_HNOTIFY -+#define AuOpt_UDBA_HNOTIFY 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 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) -+ -+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); -+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 --git a/fs/aufs/plink.c b/fs/aufs/plink.c -new file mode 100644 -index 0000000..1780fb1 ---- /dev/null -+++ b/fs/aufs/plink.c -@@ -0,0 +1,514 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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_head *plink_hlist; -+ 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++) { -+ plink_hlist = &sbinfo->si_plink[i].head; -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(icntnr, plink_hlist, plink) -+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); -+ rcu_read_unlock(); -+ } -+} -+#endif -+ -+/* is the inode pseudo-linked? */ -+int au_plink_test(struct inode *inode) -+{ -+ int found, i; -+ struct au_sbinfo *sbinfo; -+ struct hlist_head *plink_hlist; -+ 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); -+ plink_hlist = &sbinfo->si_plink[i].head; -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(icntnr, plink_hlist, plink) -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ rcu_read_unlock(); -+ 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 mutex *h_mtx; -+ -+ h_mtx = &d_inode(h_parent)->i_mutex; -+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); -+ h_dentry = vfsub_lkup_one(tgtname, h_parent); -+ mutex_unlock(h_mtx); -+ 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); -+ mutex_lock_nested(&h_dir->i_mutex, 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: -+ mutex_unlock(&h_dir->i_mutex); -+ 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_head *plink_hlist; -+ struct au_icntnr *icntnr; -+ struct au_sphlhead *sphl; -+ 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); -+ sphl = sbinfo->si_plink + i; -+ plink_hlist = &sphl->head; -+ au_igrab(inode); -+ -+ spin_lock(&sphl->spin); -+ hlist_for_each_entry(icntnr, plink_hlist, plink) { -+ if (&icntnr->vfs_inode == inode) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ icntnr = container_of(inode, struct au_icntnr, vfs_inode); -+ hlist_add_head_rcu(&icntnr->plink, plink_hlist); -+ } -+ spin_unlock(&sphl->spin); -+ if (!found) { -+ cnt = au_sphl_count(sphl); -+#define msg "unexpectedly unblanced 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_sphl_del_rcu(&icntnr->plink, sphl); -+ 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_head *plink_hlist; -+ struct hlist_node *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++) { -+ plink_hlist = &sbinfo->si_plink[i].head; -+ if (!warned && verbose && !hlist_empty(plink_hlist)) { -+ pr_warn("pseudo-link is not flushed"); -+ warned = 1; -+ } -+ hlist_for_each_entry_safe(icntnr, tmp, plink_hlist, plink) -+ iput(&icntnr->vfs_inode); -+ INIT_HLIST_HEAD(plink_hlist); -+ } -+} -+ -+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_head *plink_hlist; -+ struct hlist_node *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 spin_lock since sbinfo is write-locked */ -+ for (i = 0; i < AuPlink_NHASH; i++) { -+ plink_hlist = &sbinfo->si_plink[i].head; -+ hlist_for_each_entry_safe(icntnr, tmp, plink_hlist, 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_del(&icntnr->plink); -+ iput(inode); -+ } -+ ii_write_unlock(inode); -+ iput(inode); -+ } -+ } -+} -diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c -new file mode 100644 -index 0000000..cf7abdf ---- /dev/null -+++ b/fs/aufs/poll.c -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * poll operation -+ * There is only one filesystem which implements ->poll operation, currently. -+ */ -+ -+#include "aufs.h" -+ -+unsigned int aufs_poll(struct file *file, poll_table *wait) -+{ -+ unsigned int mask; -+ int err; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ /* We should pretend an error happened. */ -+ mask = POLLERR /* | POLLIN | POLLOUT */; -+ sb = file->f_path.dentry->d_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* it is not an error if h_file has no operation */ -+ mask = DEFAULT_POLLMASK; -+ if (h_file->f_op->poll) -+ mask = h_file->f_op->poll(h_file, wait); -+ fput(h_file); /* instead of au_read_post() */ -+ -+out: -+ si_read_unlock(sb); -+ AuTraceErr((int)mask); -+ return mask; -+} -diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c -new file mode 100644 -index 0000000..aa6257a ---- /dev/null -+++ b/fs/aufs/posix_acl.c -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2014-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 & MS_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); -+ -+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_srxattr arg = { -+ .type = AU_ACL_SET, -+ .u.acl_set = { -+ .acl = acl, -+ .type = type -+ }, -+ }; -+ -+ mutex_lock(&inode->i_mutex); -+ 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_srxattr(dentry, &arg); -+ dput(dentry); -+ err = ssz; -+ if (ssz >= 0) -+ err = 0; -+ -+out: -+ mutex_unlock(&inode->i_mutex); -+ return err; -+} -diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c -new file mode 100644 -index 0000000..b94c003 ---- /dev/null -+++ b/fs/aufs/procfs.c -@@ -0,0 +1,169 @@ -+/* -+ * Copyright (C) 2010-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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; -+ -+ err = -EBUSY; -+ if (unlikely(file->private_data)) -+ goto out; -+ -+ sb = NULL; -+ /* don't use au_sbilist_lock() here */ -+ spin_lock(&au_sbilist.spin); -+ hlist_for_each_entry(sbinfo, &au_sbilist.head, si_list) -+ if (id == sysaufs_si_id(sbinfo)) { -+ kobject_get(&sbinfo->si_kobj); -+ sb = sbinfo->si_sb; -+ break; -+ } -+ spin_unlock(&au_sbilist.spin); -+ -+ 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 | S_IWUSR, -+ 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 --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c -new file mode 100644 -index 0000000..5fdc2d9 ---- /dev/null -+++ b/fs/aufs/rdu.c -@@ -0,0 +1,388 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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; -+ -+ err = !access_ok(VERIFY_WRITE, 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)) -+ 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); -+#if 1 -+ mutex_lock(&inode->i_mutex); -+#else -+ err = mutex_lock_killable(&inode->i_mutex); -+ AuTraceErr(err); -+ if (unlikely(err)) -+ goto out; -+#endif -+ -+ 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: -+ mutex_unlock(&inode->i_mutex); -+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) -+ err = !access_ok(VERIFY_WRITE, &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 --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h -new file mode 100644 -index 0000000..2abe89f ---- /dev/null -+++ b/fs/aufs/rwsem.h -@@ -0,0 +1,198 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * simple read-write semaphore wrappers -+ */ -+ -+#ifndef __AUFS_RWSEM_H__ -+#define __AUFS_RWSEM_H__ -+ -+#ifdef __KERNEL__ -+ -+#include "debug.h" -+ -+struct au_rwsem { -+ struct rw_semaphore rwsem; -+#ifdef CONFIG_AUFS_DEBUG -+ /* just for debugging, not almighty counter */ -+ atomic_t rcnt, wcnt; -+#endif -+}; -+ -+#ifdef CONFIG_LOCKDEP -+#define au_lockdep_set_name(rw) \ -+ lockdep_set_class_and_name(&(rw)->rwsem, \ -+ /*original key*/(rw)->rwsem.dep_map.key, \ -+ /*name*/#rw) -+#else -+#define au_lockdep_set_name(rw) do {} while (0) -+#endif -+ -+#ifdef CONFIG_AUFS_DEBUG -+#define AuDbgCntInit(rw) do { \ -+ atomic_set(&(rw)->rcnt, 0); \ -+ atomic_set(&(rw)->wcnt, 0); \ -+ smp_mb(); /* atomic set */ \ -+} while (0) -+ -+#define AuDbgCnt(rw, cnt) atomic_read(&(rw)->cnt) -+#define AuDbgCntInc(rw, cnt) atomic_inc(&(rw)->cnt) -+#define AuDbgCntDec(rw, cnt) WARN_ON(atomic_dec_return(&(rw)->cnt) < 0) -+#define AuDbgRcntInc(rw) AuDbgCntInc(rw, rcnt) -+#define AuDbgRcntDec(rw) AuDbgCntDec(rw, rcnt) -+#define AuDbgWcntInc(rw) AuDbgCntInc(rw, wcnt) -+#define AuDbgWcntDec(rw) AuDbgCntDec(rw, wcnt) -+#else -+#define AuDbgCnt(rw, cnt) 0 -+#define AuDbgCntInit(rw) do {} while (0) -+#define AuDbgRcntInc(rw) do {} while (0) -+#define AuDbgRcntDec(rw) do {} while (0) -+#define AuDbgWcntInc(rw) do {} while (0) -+#define AuDbgWcntDec(rw) do {} while (0) -+#endif /* CONFIG_AUFS_DEBUG */ -+ -+/* to debug easier, do not make them inlined functions */ -+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(&(rw)->rwsem)) -+/* rwsem_is_locked() is unusable */ -+#define AuRwMustReadLock(rw) AuDebugOn(AuDbgCnt(rw, rcnt) <= 0) -+#define AuRwMustWriteLock(rw) AuDebugOn(AuDbgCnt(rw, wcnt) <= 0) -+#define AuRwMustAnyLock(rw) AuDebugOn(AuDbgCnt(rw, rcnt) <= 0 \ -+ && AuDbgCnt(rw, wcnt) <= 0) -+#define AuRwDestroy(rw) AuDebugOn(AuDbgCnt(rw, rcnt) \ -+ || AuDbgCnt(rw, wcnt)) -+ -+#define au_rw_init(rw) do { \ -+ AuDbgCntInit(rw); \ -+ init_rwsem(&(rw)->rwsem); \ -+ au_lockdep_set_name(rw); \ -+ } while (0) -+ -+#define au_rw_init_wlock(rw) do { \ -+ au_rw_init(rw); \ -+ down_write(&(rw)->rwsem); \ -+ AuDbgWcntInc(rw); \ -+ } while (0) -+ -+#define au_rw_init_wlock_nested(rw, lsc) do { \ -+ au_rw_init(rw); \ -+ down_write_nested(&(rw)->rwsem, lsc); \ -+ AuDbgWcntInc(rw); \ -+ } while (0) -+ -+static inline void au_rw_read_lock(struct au_rwsem *rw) -+{ -+ down_read(&rw->rwsem); -+ AuDbgRcntInc(rw); -+} -+ -+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc) -+{ -+ down_read_nested(&rw->rwsem, lsc); -+ AuDbgRcntInc(rw); -+} -+ -+static inline void au_rw_read_unlock(struct au_rwsem *rw) -+{ -+ AuRwMustReadLock(rw); -+ AuDbgRcntDec(rw); -+ up_read(&rw->rwsem); -+} -+ -+static inline void au_rw_dgrade_lock(struct au_rwsem *rw) -+{ -+ AuRwMustWriteLock(rw); -+ AuDbgRcntInc(rw); -+ AuDbgWcntDec(rw); -+ downgrade_write(&rw->rwsem); -+} -+ -+static inline void au_rw_write_lock(struct au_rwsem *rw) -+{ -+ down_write(&rw->rwsem); -+ AuDbgWcntInc(rw); -+} -+ -+static inline void au_rw_write_lock_nested(struct au_rwsem *rw, -+ unsigned int lsc) -+{ -+ down_write_nested(&rw->rwsem, lsc); -+ AuDbgWcntInc(rw); -+} -+ -+static inline void au_rw_write_unlock(struct au_rwsem *rw) -+{ -+ AuRwMustWriteLock(rw); -+ AuDbgWcntDec(rw); -+ up_write(&rw->rwsem); -+} -+ -+/* why is not _nested version defined */ -+static inline int au_rw_read_trylock(struct au_rwsem *rw) -+{ -+ int ret; -+ -+ ret = down_read_trylock(&rw->rwsem); -+ if (ret) -+ AuDbgRcntInc(rw); -+ return ret; -+} -+ -+static inline int au_rw_write_trylock(struct au_rwsem *rw) -+{ -+ int ret; -+ -+ ret = down_write_trylock(&rw->rwsem); -+ if (ret) -+ AuDbgWcntInc(rw); -+ return ret; -+} -+ -+#undef AuDbgCntDec -+#undef AuDbgRcntInc -+#undef AuDbgRcntDec -+#undef AuDbgWcntDec -+ -+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ -+static inline void prefix##_read_lock(param) \ -+{ au_rw_read_lock(rwsem); } \ -+static inline void prefix##_write_lock(param) \ -+{ au_rw_write_lock(rwsem); } \ -+static inline int prefix##_read_trylock(param) \ -+{ return au_rw_read_trylock(rwsem); } \ -+static inline int prefix##_write_trylock(param) \ -+{ return au_rw_write_trylock(rwsem); } -+/* why is not _nested version defined */ -+/* static inline void prefix##_read_trylock_nested(param, lsc) -+{ au_rw_read_trylock_nested(rwsem, lsc)); } -+static inline void prefix##_write_trylock_nestd(param, lsc) -+{ au_rw_write_trylock_nested(rwsem, lsc); } */ -+ -+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \ -+static inline void prefix##_read_unlock(param) \ -+{ au_rw_read_unlock(rwsem); } \ -+static inline void prefix##_write_unlock(param) \ -+{ au_rw_write_unlock(rwsem); } \ -+static inline void prefix##_downgrade_lock(param) \ -+{ au_rw_dgrade_lock(rwsem); } -+ -+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \ -+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ -+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_RWSEM_H__ */ -diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c -new file mode 100644 -index 0000000..ac586c7 ---- /dev/null -+++ b/fs/aufs/sbinfo.c -@@ -0,0 +1,308 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * superblock private data -+ */ -+ -+#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_empty(&sbinfo->si_plink[i].head)); -+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); -+ -+ AuDebugOn(percpu_counter_sum(&sbinfo->si_ninodes)); -+ percpu_counter_destroy(&sbinfo->si_ninodes); -+ AuDebugOn(percpu_counter_sum(&sbinfo->si_nfiles)); -+ percpu_counter_destroy(&sbinfo->si_nfiles); -+ -+ AuDebugOn(!hlist_empty(&sbinfo->si_symlink.head)); -+ -+ au_rw_write_lock(&sbinfo->si_rwsem); -+ au_br_free(sbinfo); -+ au_rw_write_unlock(&sbinfo->si_rwsem); -+ -+ au_delayed_kfree(sbinfo->si_branch); -+ mutex_destroy(&sbinfo->si_xib_mtx); -+ AuRwDestroy(&sbinfo->si_rwsem); -+ -+ au_delayed_kfree(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 (unlikely(err)) -+ goto out_br; -+ -+ au_nwt_init(&sbinfo->si_nowait); -+ au_rw_init_wlock(&sbinfo->si_rwsem); -+ -+ percpu_counter_init(&sbinfo->si_ninodes, 0, GFP_NOFS); -+ percpu_counter_init(&sbinfo->si_nfiles, 0, GFP_NOFS); -+ -+ 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); -+ -+ au_sphl_init(&sbinfo->si_symlink); -+ -+ 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); -+ sbinfo->si_xino_brid = -1; -+ /* leave si_xib_last_pindex and si_xib_next_bit */ -+ -+ au_sphl_init(&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++) -+ au_sphl_init(sbinfo->si_plink + i); -+ init_waitqueue_head(&sbinfo->si_plink_wq); -+ spin_lock_init(&sbinfo->si_plink_maint_lock); -+ -+ au_sphl_init(&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_delayed_kfree(sbinfo->si_branch); -+out_sbinfo: -+ au_delayed_kfree(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->i_version++; -+ 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 --git a/fs/aufs/spl.h b/fs/aufs/spl.h -new file mode 100644 -index 0000000..2845873 ---- /dev/null -+++ b/fs/aufs/spl.h -@@ -0,0 +1,113 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * simple list protected by a spinlock -+ */ -+ -+#ifndef __AUFS_SPL_H__ -+#define __AUFS_SPL_H__ -+ -+#ifdef __KERNEL__ -+ -+#if 0 -+struct au_splhead { -+ spinlock_t spin; -+ struct list_head head; -+}; -+ -+static inline void au_spl_init(struct au_splhead *spl) -+{ -+ spin_lock_init(&spl->spin); -+ INIT_LIST_HEAD(&spl->head); -+} -+ -+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl) -+{ -+ spin_lock(&spl->spin); -+ list_add(list, &spl->head); -+ spin_unlock(&spl->spin); -+} -+ -+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl) -+{ -+ spin_lock(&spl->spin); -+ list_del(list); -+ spin_unlock(&spl->spin); -+} -+ -+static inline void au_spl_del_rcu(struct list_head *list, -+ struct au_splhead *spl) -+{ -+ spin_lock(&spl->spin); -+ list_del_rcu(list); -+ spin_unlock(&spl->spin); -+} -+#endif -+ -+/* ---------------------------------------------------------------------- */ -+ -+struct au_sphlhead { -+ spinlock_t spin; -+ struct hlist_head head; -+}; -+ -+static inline void au_sphl_init(struct au_sphlhead *sphl) -+{ -+ spin_lock_init(&sphl->spin); -+ INIT_HLIST_HEAD(&sphl->head); -+} -+ -+static inline void au_sphl_add(struct hlist_node *hlist, -+ struct au_sphlhead *sphl) -+{ -+ spin_lock(&sphl->spin); -+ hlist_add_head(hlist, &sphl->head); -+ spin_unlock(&sphl->spin); -+} -+ -+static inline void au_sphl_del(struct hlist_node *hlist, -+ struct au_sphlhead *sphl) -+{ -+ spin_lock(&sphl->spin); -+ hlist_del(hlist); -+ spin_unlock(&sphl->spin); -+} -+ -+static inline void au_sphl_del_rcu(struct hlist_node *hlist, -+ struct au_sphlhead *sphl) -+{ -+ spin_lock(&sphl->spin); -+ hlist_del_rcu(hlist); -+ spin_unlock(&sphl->spin); -+} -+ -+static inline unsigned long au_sphl_count(struct au_sphlhead *sphl) -+{ -+ unsigned long cnt; -+ struct hlist_node *pos; -+ -+ cnt = 0; -+ spin_lock(&sphl->spin); -+ hlist_for_each(pos, &sphl->head) -+ cnt++; -+ spin_unlock(&sphl->spin); -+ return cnt; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_SPL_H__ */ -diff --git a/fs/aufs/super.c b/fs/aufs/super.c -new file mode 100644 -index 0000000..08b691f ---- /dev/null -+++ b/fs/aufs/super.c -@@ -0,0 +1,1044 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * mount and super_block operations -+ */ -+ -+#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); -+ c->vfs_inode.i_version = 1; /* sigen(sb); */ -+ c->iinfo.ii_hinode = NULL; -+ return &c->vfs_inode; -+ } -+ return NULL; -+} -+ -+static void aufs_destroy_inode_cb(struct rcu_head *head) -+{ -+ struct inode *inode = container_of(head, struct inode, i_rcu); -+ -+ au_cache_dfree_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); -+} -+ -+static void aufs_destroy_inode(struct inode *inode) -+{ -+ if (!au_is_bad_inode(inode)) -+ au_iinfo_fin(inode); -+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb); -+} -+ -+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->i_version++; -+ 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; -+ -+ 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; -+ brid = au_xino_brid(sb); -+ if (brid >= 0) { -+ bindex = au_br_index(sb, brid); -+ h_root = au_hdentry(au_di(sb->s_root), bindex)->hd_dentry; -+ } -+ 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 & MS_POSIXACL) -+ seq_puts(m, ",acl"); -+ -+ /* 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(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) -+ return; -+ -+ dbgaufs_si_fin(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) -+{ -+ *max = au_ninodes(sb); -+ 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 %pf and %pf\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); -+ mutex_lock(&inode->i_mutex); -+ 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: -+ mutex_unlock(&inode->i_mutex); -+out_opts: -+ au_delayed_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, -+ /* 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 |= MS_NOATIME | MS_NODIRATIME; -+ 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. */ -+ mutex_lock(&inode->i_mutex); -+ 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("%pf\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); -+ mutex_unlock(&inode->i_mutex); -+ if (!err) -+ goto out_opts; /* success */ -+ -+out_root: -+ dput(root); -+ sb->s_root = NULL; -+out_info: -+ dbgaufs_si_fin(sbinfo); -+ kobject_put(&sbinfo->si_kobj); -+ sb->s_fs_info = NULL; -+out_opts: -+ au_delayed_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; -+ struct super_block *sb; -+ -+ /* 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; -+ -+ sb = root->d_sb; -+ si_write_lock(sb, !AuLock_FLUSH); -+ sysaufs_brs_add(sb, 0); -+ si_write_unlock(sb); -+ au_sbilist_add(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); -+ 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 --git a/fs/aufs/super.h b/fs/aufs/super.h -new file mode 100644 -index 0000000..bcddbfd ---- /dev/null -+++ b/fs/aufs/super.h -@@ -0,0 +1,619 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * super_block operations -+ */ -+ -+#ifndef __AUFS_SUPER_H__ -+#define __AUFS_SUPER_H__ -+ -+#ifdef __KERNEL__ -+ -+#include -+#include -+#include "rwsem.h" -+#include "spl.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 dependecy 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. -+ */ -+ struct percpu_counter 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; -+ -+ /* symlink to follow_link() and put_link() */ -+ struct au_sphlhead si_symlink; -+ -+ /* external inode number (bitmap and translation table) */ -+ vfs_readf_t si_xread; -+ vfs_writef_t si_xwrite; -+ 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; -+ aufs_bindex_t si_xino_brid; -+ 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 */ -+ struct file *si_xigen; -+ atomic_t si_xigen_next; -+#endif -+ -+ /* dirty trick to suppoer atomic_open */ -+ struct au_sphlhead 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 au_sphlhead 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 au_sphlhead 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, particulary 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_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 unnecesary -+ */ -+#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 */ -+#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 file *base); -+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 file *base) -+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 au_sphlhead au_sbilist; -+ -+static inline void au_sbilist_init(void) -+{ -+ au_sphl_init(&au_sbilist); -+} -+ -+static inline void au_sbilist_add(struct super_block *sb) -+{ -+ au_sphl_add(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+static inline void au_sbilist_del(struct super_block *sb) -+{ -+ au_sphl_del(&au_sbi(sb)->si_list, &au_sbilist); -+} -+ -+#ifdef CONFIG_AUFS_MAGIC_SYSRQ -+static inline void au_sbilist_lock(void) -+{ -+ spin_lock(&au_sbilist.spin); -+} -+ -+static inline void au_sbilist_unlock(void) -+{ -+ spin_unlock(&au_sbilist.spin); -+} -+#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 7 -+ -+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 */ -+/* -+ * __si_read_lock, __si_write_lock, -+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock -+ */ -+AuSimpleRwsemFuncs(__si, struct super_block *sb, &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 unsigned long long au_ninodes(struct super_block *sb) -+{ -+ s64 n = percpu_counter_sum(&au_sbi(sb)->si_ninodes); -+ -+ BUG_ON(n < 0); -+ return n; -+} -+ -+static inline void au_ninodes_inc(struct super_block *sb) -+{ -+ percpu_counter_inc(&au_sbi(sb)->si_ninodes); -+} -+ -+static inline void au_ninodes_dec(struct super_block *sb) -+{ -+ percpu_counter_dec(&au_sbi(sb)->si_ninodes); -+} -+ -+static inline unsigned long long au_nfiles(struct super_block *sb) -+{ -+ s64 n = percpu_counter_sum(&au_sbi(sb)->si_nfiles); -+ -+ BUG_ON(n < 0); -+ return n; -+} -+ -+static inline void au_nfiles_inc(struct super_block *sb) -+{ -+ percpu_counter_inc(&au_sbi(sb)->si_nfiles); -+} -+ -+static inline void au_nfiles_dec(struct super_block *sb) -+{ -+ percpu_counter_dec(&au_sbi(sb)->si_nfiles); -+} -+ -+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 void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid) -+{ -+ SiMustWriteLock(sb); -+ au_sbi(sb)->si_xino_brid = brid; -+} -+ -+static inline aufs_bindex_t au_xino_brid(struct super_block *sb) -+{ -+ SiMustAnyLock(sb); -+ return au_sbi(sb)->si_xino_brid; -+} -+ -+#endif /* __KERNEL__ */ -+#endif /* __AUFS_SUPER_H__ */ -diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c -new file mode 100644 -index 0000000..3f172fd ---- /dev/null -+++ b/fs/aufs/sysaufs.c -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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)); -+ -+ dbgaufs_si_null(sbinfo); -+ if (!err) { -+ err = dbgaufs_si_init(sbinfo); -+ if (unlikely(err)) -+ kobject_put(&sbinfo->si_kobj); -+ } -+ return err; -+} -+ -+void sysaufs_fin(void) -+{ -+ dbgaufs_fin(); -+ 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); -+ goto out; -+ } -+ -+ err = dbgaufs_init(); -+ if (unlikely(err)) -+ sysaufs_fin(); -+out: -+ return err; -+} -diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h -new file mode 100644 -index 0000000..3330733 ---- /dev/null -+++ b/fs/aufs/sysaufs.h -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c -new file mode 100644 -index 0000000..ccbd98e ---- /dev/null -+++ b/fs/aufs/sysfs.c -@@ -0,0 +1,376 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * sysfs interface -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+#ifdef CONFIG_AUFS_FS_MODULE -+/* this entry violates the "one line per file" policy of sysfs */ -+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr, -+ char *buf) -+{ -+ ssize_t err; -+ static char *conf = -+/* this file is generated at compiling */ -+#include "conf.str" -+ ; -+ -+ err = snprintf(buf, PAGE_SIZE, conf); -+ if (unlikely(err >= PAGE_SIZE)) -+ err = -EFBIG; -+ return err; -+} -+ -+static struct kobj_attribute au_config_attr = __ATTR_RO(config); -+#endif -+ -+static struct attribute *au_attr[] = { -+#ifdef CONFIG_AUFS_FS_MODULE -+ &au_config_attr.attr, -+#endif -+ 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_delayed_kfree(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++) { -+ err = !access_ok(VERIFY_WRITE, 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_delayed_kfree(seq); -+out_buf: -+ au_delayed_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 = S_IRUGO; -+ 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; -+ -+ dbgaufs_brs_del(sb, bindex); -+ -+ 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; -+ -+ dbgaufs_brs_add(sb, bindex); -+ -+ 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 --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c -new file mode 100644 -index 0000000..98d5ad2 ---- /dev/null -+++ b/fs/aufs/sysrq.c -@@ -0,0 +1,157 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * magic sysrq hanlder -+ */ -+ -+/* #include */ -+#include -+#include "aufs.h" -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void sysrq_sb(struct super_block *sb) -+{ -+ char *plevel; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ struct au_sphlhead *files; -+ 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; -+ spin_lock(&files->spin); -+ hlist_for_each_entry(finfo, &files->head, fi_hlist) { -+ umode_t mode; -+ -+ file = finfo->fi_file; -+ mode = file_inode(file)->i_mode; -+ if (!special_file(mode)) -+ au_dpri_file(file); -+ } -+ spin_unlock(&files->spin); -+ pr("done\n"); -+ -+#undef pr -+ au_plevel = plevel; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* module parameter */ -+static char *aufs_sysrq_key = "a"; -+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO); -+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); -+ -+static void au_sysrq(int key __maybe_unused) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ lockdep_off(); -+ au_sbilist_lock(); -+ hlist_for_each_entry(sbinfo, &au_sbilist.head, 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 --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c -new file mode 100644 -index 0000000..5100c6e ---- /dev/null -+++ b/fs/aufs/vdir.c -@@ -0,0 +1,899 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * virtual or vertical directory -+ */ -+ -+#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_delayed_kfree(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_dfree_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_delayed_kfree(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, int atonce) -+{ -+ unsigned char **deblk; -+ -+ deblk = vdir->vd_deblk; -+ if (!atonce) { -+ while (vdir->vd_nblk--) -+ au_delayed_kfree(*deblk++); -+ au_delayed_kfree(vdir->vd_deblk); -+ au_cache_dfree_vdir(vdir); -+ } else { -+ /* not delayed */ -+ while (vdir->vd_nblk--) -+ kfree(*deblk++); -+ kfree(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_delayed_kfree(vdir->vd_deblk); -+ -+out_free: -+ au_cache_dfree_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_delayed_kfree(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 */ -+ -+ 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; -+ } -+ } -+ -+ au_delayed_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); -+ 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->i_version != 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->i_version; -+ 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, /*atonce*/0); -+ -+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->i_version; -+ if (allocated) -+ au_set_fvdir_cache(file, allocated); -+ } else if (allocated) -+ au_vdir_free(allocated, /*atonce*/0); -+ -+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(); */ -+ AuTraceErr(!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; -+ -+ vdir_cache = au_fvdir_cache(file); -+ if (!seek_vdir(file, ctx)) -+ return 0; -+ -+ 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 --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c -new file mode 100644 -index 0000000..61a3a09 ---- /dev/null -+++ b/fs/aufs/vfsub.c -@@ -0,0 +1,881 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * sub-routines for VFS -+ */ -+ -+#include -+#include -+#include -+#include -+#ifdef CONFIG_AUFS_BR_FUSE -+#include "../fs/mount.h" -+#endif -+#include "aufs.h" -+ -+#ifdef CONFIG_AUFS_BR_FUSE -+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) -+{ -+ struct nsproxy *ns; -+ -+ if (!au_test_fuse(h_sb) || !au_userns) -+ return 0; -+ -+ ns = current->nsproxy; -+ /* no {get,put}_nsproxy(ns) */ -+ return real_mount(mnt)->mnt_ns == ns->mnt_ns ? 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 = vfs_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, struct au_branch *br) -+{ -+ int err; -+ 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; -+ -+ args->file->f_path.dentry = DENTRY_NOT_SET; -+ args->file->f_path.mnt = au_br_mnt(br); -+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, -+ args->create_mode, args->opened); -+ if (err >= 0) { -+ /* some filesystems don't set FILE_CREATED while succeeded? */ -+ if (*args->opened & FILE_CREATED) -+ fsnotify_create(dir, dentry); -+ } else -+ goto out; -+ -+ -+ if (!err) { -+ /* todo: call VFS:may_open() here */ -+ err = open_check_o_direct(file); -+ /* todo: ima_file_check() too? */ -+ if (!err && (args->open_flag & __FMODE_EXEC)) -+ err = deny_write_access(file); -+ if (unlikely(err)) -+ /* note that the file is created and still opened */ -+ goto out; -+ } -+ -+ au_br_get(br); -+ fsnotify_open(file); -+ -+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(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) -+{ -+ 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*/0); -+ 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{%pf, %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 --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h -new file mode 100644 -index 0000000..05dec4e ---- /dev/null -+++ b/fs/aufs/vfsub.h -@@ -0,0 +1,316 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 int open_check_o_direct(struct file *f); -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* 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) MtxMustLock(&(i)->i_mutex) -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 (inode->i_sb->s_flags & MS_RDONLY) -+ || 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 vfsub_aopen_args { -+ struct file *file; -+ unsigned int open_flag; -+ umode_t create_mode; -+ int *opened; -+}; -+struct au_branch; -+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, -+ struct vfsub_aopen_args *args, struct au_branch *br); -+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); -+ -+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); -+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 timespec *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); -+ -+/* ---------------------------------------------------------------------- */ -+ -+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_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 --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c -new file mode 100644 -index 0000000..82c4948 ---- /dev/null -+++ b/fs/aufs/wbr_policy.c -@@ -0,0 +1,830 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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, -+ S_IRWXU | S_IRUGO | S_IXUGO); -+ 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); -+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); -+ if (au_ftest_cpdown(*flags, WHED)) { -+ err = au_cpdown_dir_opq(dentry, bdst, flags); -+ if (unlikely(err)) { -+ mutex_unlock(&h_inode->i_mutex); -+ goto out_dir; -+ } -+ } -+ -+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); -+ mutex_unlock(&h_inode->i_mutex); -+ 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)) { -+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); -+ rerr = au_diropq_remove(dentry, bdst); -+ mutex_unlock(&h_inode->i_mutex); -+ 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_delayed_kfree(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 --git a/fs/aufs/whout.c b/fs/aufs/whout.c -new file mode 100644 -index 0000000..17de340 ---- /dev/null -+++ b/fs/aufs/whout.c -@@ -0,0 +1,1060 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * whiteout for logical deletion and opaque directory -+ */ -+ -+#include "aufs.h" -+ -+#define WH_MASK S_IRUGO -+ -+/* -+ * 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_delayed_kfree(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); -+ 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 = S_IRWXU; -+ -+ if (au_test_nfs(path->dentry->d_sb)) -+ mode |= S_IXUGO; -+ 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: succuess -+ * 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_imtx_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_imtx_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_br_put(a->br); -+ si_write_unlock(a->sb); -+ au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ au_delayed_kfree(arg); -+ 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_br_get(br); -+ 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_br_put(br); -+ au_delayed_kfree(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_delayed_kfree(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; -+ } -+ } -+ au_delayed_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_delayed_kfree(whtmp); -+ whtmp = ERR_PTR(err); -+ } -+ -+out: -+ return whtmp; -+} -+ -+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) -+{ -+ if (whtmp->br) -+ au_br_put(whtmp->br); -+ dput(whtmp->wh_dentry); -+ iput(whtmp->dir); -+ au_nhash_wh_free(&whtmp->whlist); -+ au_delayed_kfree(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); -+ mutex_lock_nested(&wh_inode->i_mutex, 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; -+ } -+ mutex_unlock(&wh_inode->i_mutex); -+ -+ 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 */ -+ /* mutex_lock(&a->dir->i_mutex); */ -+ 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_imtx_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_imtx_unlock(hdir); -+ vfsub_mnt_drop_write(au_br_mnt(a->br)); -+ -+out_mnt: -+ dput(h_parent); -+ ii_write_unlock(a->dir); -+out: -+ /* mutex_unlock(&a->dir->i_mutex); */ -+ 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_br_get(args->br); -+ 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 --git a/fs/aufs/whout.h b/fs/aufs/whout.h -new file mode 100644 -index 0000000..eb4b182 ---- /dev/null -+++ b/fs/aufs/whout.h -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * 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 --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c -new file mode 100644 -index 0000000..aab4f30 ---- /dev/null -+++ b/fs/aufs/wkq.c -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new dredential 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; -+ -+ struct completion *comp; -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ -+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); -+ -+ wkinfo->func(wkinfo->args); -+ if (au_ftest_wkq(wkinfo->flags, WAIT)) -+ complete(wkinfo->comp); -+ else { -+ kobject_put(wkinfo->kobj); -+ module_put(THIS_MODULE); /* todo: ?? */ -+ au_delayed_kfree(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_delayed_kfree(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?\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 (!err) { -+ au_wkq_run(&wkinfo); -+ /* no timeout, no interrupt */ -+ wait_for_completion(wkinfo.comp); -+ au_wkq_comp_free(comp); -+ 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; -+ 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 --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h -new file mode 100644 -index 0000000..a0a253b ---- /dev/null -+++ b/fs/aufs/wkq.h -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * workqueue for asynchronous/super-io operations -+ * todo: try new credentials management scheme -+ */ -+ -+#ifndef __AUFS_WKQ_H__ -+#define __AUFS_WKQ_H__ -+ -+#ifdef __KERNEL__ -+ -+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) -+ -+#ifndef CONFIG_AUFS_HNOTIFY -+#undef AuWkq_NEST -+#define AuWkq_NEST 0 -+#endif -+ -+/* 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 --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c -new file mode 100644 -index 0000000..0aba12b ---- /dev/null -+++ b/fs/aufs/xattr.c -@@ -0,0 +1,365 @@ -+/* -+ * Copyright (C) 2014-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * handling xattr functions -+ */ -+ -+#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); -+ mutex_unlock(&h_idst->i_mutex); -+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); -+ mutex_lock_nested(&h_idst->i_mutex, 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); -+ mutex_unlock(&h_idst->i_mutex); -+ mutex_lock_nested(&h_isrc->i_mutex, AuLsc_I_CHILD); -+ mutex_lock_nested(&h_idst->i_mutex, 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); -+ } -+ mutex_unlock(&h_isrc->i_mutex); -+ 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); -+ } -+ -+ if (value) -+ au_delayed_kfree(value); -+ -+out_free: -+ if (o) -+ au_delayed_kfree(o); -+out: -+ if (!unlocked) -+ mutex_unlock(&h_isrc->i_mutex); -+ 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: -+ 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); -+} -+ -+ssize_t aufs_getxattr(struct dentry *dentry, 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); -+} -+ -+int aufs_setxattr(struct dentry *dentry, const char *name, const void *value, -+ size_t size, int flags) -+{ -+ struct au_srxattr arg = { -+ .type = AU_XATTR_SET, -+ .u.set = { -+ .name = name, -+ .value = value, -+ .size = size, -+ .flags = flags -+ }, -+ }; -+ -+ return au_srxattr(dentry, &arg); -+} -+ -+int aufs_removexattr(struct dentry *dentry, const char *name) -+{ -+ struct au_srxattr arg = { -+ .type = AU_XATTR_REMOVE, -+ .u.remove = { -+ .name = name -+ }, -+ }; -+ -+ return au_srxattr(dentry, &arg); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+#if 0 -+static size_t au_xattr_list(struct dentry *dentry, char *list, size_t list_size, -+ const char *name, size_t name_len, int type) -+{ -+ return aufs_listxattr(dentry, list, list_size); -+} -+ -+static int au_xattr_get(struct dentry *dentry, const char *name, void *buffer, -+ size_t size, int type) -+{ -+ return aufs_getxattr(dentry, name, buffer, size); -+} -+ -+static int au_xattr_set(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags, int type) -+{ -+ return aufs_setxattr(dentry, name, value, size, flags); -+} -+ -+static const struct xattr_handler au_xattr_handler = { -+ /* no prefix, no flags */ -+ .list = au_xattr_list, -+ .get = au_xattr_get, -+ .set = au_xattr_set -+ /* why no remove? */ -+}; -+ -+static const struct xattr_handler *au_xattr_handlers[] = { -+ &au_xattr_handler -+}; -+ -+void au_xattr_init(struct super_block *sb) -+{ -+ /* sb->s_xattr = au_xattr_handlers; */ -+} -+#endif -diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c -new file mode 100644 -index 0000000..492d632 ---- /dev/null -+++ b/fs/aufs/xino.c -@@ -0,0 +1,1318 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+/* -+ * external inode number translation table and bitmap -+ */ -+ -+#include -+#include -+#include "aufs.h" -+ -+/* 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; -+ -+ 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); -+ set_fs(oldfs); -+ -+#if 0 /* reserved for future use */ -+ if (err > 0) -+ fsnotify_access(file->f_path.dentry); -+#endif -+ -+ 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 -+ err = xino_fwrite_wkq(func, file, buf, size, pos); -+ -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * create a new xinofile at the same place/path as @base_file. -+ */ -+struct file *au_xino_create2(struct file *base_file, struct file *copy_src) -+{ -+ struct file *file; -+ struct dentry *base, *parent; -+ struct inode *dir, *delegated; -+ struct qstr *name; -+ struct path path; -+ int err; -+ -+ base = base_file->f_path.dentry; -+ parent = base->d_parent; /* dir inode is locked */ -+ dir = d_inode(parent); -+ IMustLock(dir); -+ -+ file = ERR_PTR(-EINVAL); -+ name = &base->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", -+ base, PTR_ERR(path.dentry)); -+ goto out; -+ } -+ -+ /* no need to mnt_want_write() since we call dentry_open() later */ -+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL); -+ if (unlikely(err)) { -+ file = ERR_PTR(err); -+ pr_err("%pd create err %d\n", base, err); -+ goto out_dput; -+ } -+ -+ path.mnt = base_file->f_path.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", base, PTR_ERR(file)); -+ goto out_dput; -+ } -+ -+ delegated = NULL; -+ err = vfsub_unlink(dir, &file->f_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)) { -+ pr_err("%pd unlink err %d\n", base, 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", base, err); -+ goto out_fput; -+ } -+ } -+ goto out_dput; /* success */ -+ -+out_fput: -+ fput(file); -+ file = ERR_PTR(err); -+out_dput: -+ dput(path.dentry); -+out: -+ return file; -+} -+ -+struct au_xino_lock_dir { -+ struct au_hinode *hdir; -+ struct dentry *parent; -+ struct mutex *mtx; -+}; -+ -+static void au_xino_lock_dir(struct super_block *sb, struct file *xino, -+ struct au_xino_lock_dir *ldir) -+{ -+ aufs_bindex_t brid, bindex; -+ -+ ldir->hdir = NULL; -+ bindex = -1; -+ brid = au_xino_brid(sb); -+ if (brid >= 0) -+ bindex = au_br_index(sb, brid); -+ if (bindex >= 0) { -+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); -+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT); -+ } else { -+ ldir->parent = dget_parent(xino->f_path.dentry); -+ ldir->mtx = &d_inode(ldir->parent)->i_mutex; -+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT); -+ } -+} -+ -+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) -+{ -+ if (ldir->hdir) -+ au_hn_imtx_unlock(ldir->hdir); -+ else { -+ mutex_unlock(ldir->mtx); -+ dput(ldir->parent); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* trucate xino files asynchronously */ -+ -+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex) -+{ -+ int err; -+ unsigned long jiffy; -+ blkcnt_t blocks; -+ aufs_bindex_t bi, bbot; -+ struct kstatfs *st; -+ struct au_branch *br; -+ struct file *new_xino, *file; -+ struct super_block *h_sb; -+ struct au_xino_lock_dir ldir; -+ -+ 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; -+ br = au_sbr(sb, bindex); -+ file = br->br_xino.xi_file; -+ if (!file) -+ goto out_st; -+ -+ err = vfs_statfs(&file->f_path, st); -+ if (unlikely(err)) -+ AuErr1("statfs err %d, ignored\n", err); -+ jiffy = jiffies; -+ blocks = file_inode(file)->i_blocks; -+ pr_info("begin truncating xino(b%d), ib%llu, %llu/%llu free blks\n", -+ bindex, (u64)blocks, st->f_bfree, st->f_blocks); -+ -+ au_xino_lock_dir(sb, file, &ldir); -+ /* mnt_want_write() is unnecessary here */ -+ new_xino = au_xino_create2(file, file); -+ au_xino_unlock_dir(&ldir); -+ err = PTR_ERR(new_xino); -+ if (IS_ERR(new_xino)) { -+ pr_err("err %d, ignored\n", err); -+ goto out_st; -+ } -+ err = 0; -+ fput(file); -+ br->br_xino.xi_file = new_xino; -+ -+ h_sb = au_br_sb(br); -+ for (bi = 0; bi <= bbot; bi++) { -+ if (unlikely(bi == bindex)) -+ continue; -+ br = au_sbr(sb, bi); -+ if (au_br_sb(br) != h_sb) -+ continue; -+ -+ fput(br->br_xino.xi_file); -+ br->br_xino.xi_file = new_xino; -+ get_file(new_xino); -+ } -+ -+ err = vfs_statfs(&new_xino->f_path, st); -+ if (!err) { -+ pr_info("end truncating xino(b%d), ib%llu, %llu/%llu free blks\n", -+ bindex, (u64)file_inode(new_xino)->i_blocks, -+ st->f_bfree, st->f_blocks); -+ if (file_inode(new_xino)->i_blocks < blocks) -+ au_sbi(sb)->si_xino_jiffy = jiffy; -+ } else -+ AuErr1("statfs err %d, ignored\n", err); -+ -+out_st: -+ au_delayed_kfree(st); -+out: -+ return err; -+} -+ -+struct xino_do_trunc_args { -+ struct super_block *sb; -+ struct au_branch *br; -+}; -+ -+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; -+ aufs_bindex_t bindex; -+ -+ err = 0; -+ sb = args->sb; -+ dir = d_inode(sb->s_root); -+ br = args->br; -+ -+ si_noflush_write_lock(sb); -+ ii_read_lock_parent(dir); -+ bindex = au_br_index(sb, br->br_id); -+ err = au_xino_trunc(sb, bindex); -+ ii_read_unlock(dir); -+ if (unlikely(err)) -+ pr_warn("err b%d, (%d)\n", bindex, err); -+ atomic_dec(&br->br_xino_running); -+ au_br_put(br); -+ si_write_unlock(sb); -+ au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_delayed_kfree(args); -+} -+ -+static int xino_trunc_test(struct super_block *sb, struct au_branch *br) -+{ -+ int err; -+ struct kstatfs st; -+ struct au_sbinfo *sbinfo; -+ -+ /* 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 0; -+ -+ /* truncation border */ -+ err = vfs_statfs(&br->br_xino.xi_file->f_path, &st); -+ if (unlikely(err)) { -+ AuErr1("statfs err %d, ignored\n", err); -+ return 0; -+ } -+ if (div64_u64(st.f_bfree * 100, st.f_blocks) >= AUFS_XINO_DEF_TRUNC) -+ return 0; -+ -+ return 1; -+} -+ -+static void xino_try_trunc(struct super_block *sb, struct au_branch *br) -+{ -+ struct xino_do_trunc_args *args; -+ int wkq_err; -+ -+ if (!xino_trunc_test(sb, br)) -+ return; -+ -+ if (atomic_inc_return(&br->br_xino_running) > 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_br_get(br); -+ args->sb = sb; -+ args->br = br; -+ 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_br_put(br); -+ au_delayed_kfree(args); -+ -+out: -+ atomic_dec(&br->br_xino_running); -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ ino_t h_ino, ino_t ino) -+{ -+ loff_t pos; -+ ssize_t sz; -+ -+ pos = h_ino; -+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) { -+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); -+ return -EFBIG; -+ } -+ pos *= sizeof(ino); -+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &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_branch *br; -+ -+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max) -+ || ((loff_t)-1) > 0); -+ SiMustAnyLock(sb); -+ -+ mnt_flags = au_mntflags(sb); -+ if (!au_opt_test(mnt_flags, XINO)) -+ return 0; -+ -+ br = au_sbr(sb, bindex); -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file, -+ h_ino, ino); -+ if (!err) { -+ 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 */ -+ } -+ -+ AuIOErr("write failed (%d)\n", err); -+ return -EIO; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* aufs 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); -+} -+ -+/* 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; -+ -+ 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); -+ err = au_xino_do_write(xwrite, br->br_xino.xi_file, -+ h_inode->i_ino, /*ino*/0); -+ if (!err && try_trunc -+ && au_test_fs_trunc_xino(au_br_sb(br))) -+ xino_try_trunc(sb, br); -+ } -+} -+ -+/* 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; -+} -+ -+/* -+ * read @ino from xinofile for the specified branch{@sb, @bindex} -+ * at the position of @h_ino. -+ * if @ino does not exist and @do_new is true, get new one. -+ */ -+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, -+ ino_t *ino) -+{ -+ int err; -+ ssize_t sz; -+ loff_t pos; -+ struct file *file; -+ struct au_sbinfo *sbinfo; -+ -+ *ino = 0; -+ if (!au_opt_test(au_mntflags(sb), XINO)) -+ return 0; /* no xino */ -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ pos = h_ino; -+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) { -+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); -+ return -EFBIG; -+ } -+ pos *= sizeof(*ino); -+ -+ file = au_sbr(sb, bindex)->br_xino.xi_file; -+ if (vfsub_f_size_read(file) < pos + sizeof(*ino)) -+ return 0; /* no ino */ -+ -+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* create and set a new xino file */ -+ -+struct file *au_xino_create(struct super_block *sb, char *fname, int silent) -+{ -+ struct file *file; -+ struct dentry *h_parent, *d; -+ struct inode *h_dir, *inode; -+ int err; -+ -+ /* -+ * 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. -+ */ -+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE -+ /* | __FMODE_NONOTIFY */, -+ S_IRUGO | S_IWUGO); -+ if (IS_ERR(file)) { -+ if (!silent) -+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file)); -+ return file; -+ } -+ -+ /* keep file count */ -+ err = 0; -+ inode = file_inode(file); -+ h_parent = dget_parent(file->f_path.dentry); -+ h_dir = d_inode(h_parent); -+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); -+ /* mnt_want_write() is unnecessary here */ -+ /* no delegation since it is just created */ -+ if (inode->i_nlink) -+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, -+ /*force*/0); -+ mutex_unlock(&h_dir->i_mutex); -+ dput(h_parent); -+ if (unlikely(err)) { -+ if (!silent) -+ pr_err("unlink %s(%d)\n", fname, err); -+ goto out; -+ } -+ -+ err = -EINVAL; -+ d = file->f_path.dentry; -+ if (unlikely(sb == d->d_sb)) { -+ if (!silent) -+ pr_err("%s must be outside\n", fname); -+ goto out; -+ } -+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { -+ if (!silent) -+ pr_err("xino doesn't support %s(%s)\n", -+ fname, au_sbtype(d->d_sb)); -+ goto out; -+ } -+ return file; /* success */ -+ -+out: -+ fput(file); -+ file = ERR_PTR(err); -+ return file; -+} -+ -+/* -+ * find another branch who is on the same filesystem of the specified -+ * branch{@btgt}. search until @bbot. -+ */ -+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, -+ aufs_bindex_t bbot) -+{ -+ aufs_bindex_t bindex; -+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt); -+ -+ for (bindex = 0; bindex < btgt; bindex++) -+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) -+ return bindex; -+ for (bindex++; bindex <= bbot; bindex++) -+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) -+ return bindex; -+ return -1; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * 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 @do_test is true. -+ */ -+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, -+ struct file *base_file, int do_test) -+{ -+ int err; -+ ino_t ino; -+ aufs_bindex_t bbot, bindex; -+ struct au_branch *shared_br, *b; -+ struct file *file; -+ struct super_block *tgt_sb; -+ -+ shared_br = NULL; -+ bbot = au_sbbot(sb); -+ if (do_test) { -+ tgt_sb = au_br_sb(br); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ b = au_sbr(sb, bindex); -+ if (tgt_sb == au_br_sb(b)) { -+ shared_br = b; -+ break; -+ } -+ } -+ } -+ -+ if (!shared_br || !shared_br->br_xino.xi_file) { -+ struct au_xino_lock_dir ldir; -+ -+ au_xino_lock_dir(sb, base_file, &ldir); -+ /* mnt_want_write() is unnecessary here */ -+ file = au_xino_create2(base_file, NULL); -+ au_xino_unlock_dir(&ldir); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ br->br_xino.xi_file = file; -+ } else { -+ br->br_xino.xi_file = shared_br->br_xino.xi_file; -+ get_file(br->br_xino.xi_file); -+ } -+ -+ ino = AUFS_ROOT_INO; -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file, -+ h_ino, ino); -+ if (unlikely(err)) { -+ fput(br->br_xino.xi_file); -+ br->br_xino.xi_file = NULL; -+ } -+ -+out: -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* trucate 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; -+ aufs_bindex_t bindex, bbot; -+ void *page; -+ -+ 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) -+ err = do_xib_restore -+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page); -+ else -+ AuDbg("b%d\n", bindex); -+ au_delayed_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_xino_lock_dir ldir; -+ 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; -+ -+ au_xino_lock_dir(sb, file, &ldir); -+ /* mnt_want_write() is unnecessary here */ -+ file = au_xino_create2(sbinfo->si_xib, NULL); -+ au_xino_unlock_dir(&ldir); -+ 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; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+/* -+ * 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); -+ sbinfo->si_xread = NULL; -+ sbinfo->si_xwrite = NULL; -+ if (sbinfo->si_xib) -+ fput(sbinfo->si_xib); -+ sbinfo->si_xib = NULL; -+ if (sbinfo->si_xib_buf) -+ au_delayed_free_page((unsigned long)sbinfo->si_xib_buf); -+ sbinfo->si_xib_buf = NULL; -+} -+ -+static int au_xino_set_xib(struct super_block *sb, struct file *base) -+{ -+ int err; -+ loff_t pos; -+ struct au_sbinfo *sbinfo; -+ struct file *file; -+ -+ SiMustWriteLock(sb); -+ -+ sbinfo = au_sbi(sb); -+ file = au_xino_create2(base, 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); -+ -+ 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) -+ au_delayed_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; -+ sbinfo->si_xread = NULL; -+ sbinfo->si_xwrite = NULL; -+out: -+ 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); -+ if (!br || !br->br_xino.xi_file) -+ continue; -+ -+ fput(br->br_xino.xi_file); -+ br->br_xino.xi_file = NULL; -+ } -+} -+ -+static int au_xino_set_br(struct super_block *sb, struct file *base) -+{ -+ int err; -+ ino_t ino; -+ aufs_bindex_t bindex, bbot, bshared; -+ struct { -+ struct file *old, *new; -+ } *fpair, *p; -+ struct au_branch *br; -+ struct inode *inode; -+ vfs_writef_t writef; -+ -+ SiMustWriteLock(sb); -+ -+ err = -ENOMEM; -+ bbot = au_sbbot(sb); -+ fpair = kcalloc(bbot + 1, sizeof(*fpair), GFP_NOFS); -+ if (unlikely(!fpair)) -+ goto out; -+ -+ inode = d_inode(sb->s_root); -+ ino = AUFS_ROOT_INO; -+ writef = au_sbi(sb)->si_xwrite; -+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++) { -+ bshared = is_sb_shared(sb, bindex, bindex - 1); -+ if (bshared >= 0) { -+ /* shared xino */ -+ *p = fpair[bshared]; -+ get_file(p->new); -+ } -+ -+ if (!p->new) { -+ /* new xino */ -+ br = au_sbr(sb, bindex); -+ p->old = br->br_xino.xi_file; -+ p->new = au_xino_create2(base, br->br_xino.xi_file); -+ err = PTR_ERR(p->new); -+ if (IS_ERR(p->new)) { -+ p->new = NULL; -+ goto out_pair; -+ } -+ } -+ -+ err = au_xino_do_write(writef, p->new, -+ au_h_iptr(inode, bindex)->i_ino, ino); -+ if (unlikely(err)) -+ goto out_pair; -+ } -+ -+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++) { -+ br = au_sbr(sb, bindex); -+ if (br->br_xino.xi_file) -+ fput(br->br_xino.xi_file); -+ get_file(p->new); -+ br->br_xino.xi_file = p->new; -+ } -+ -+out_pair: -+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++) -+ if (p->new) -+ fput(p->new); -+ else -+ break; -+ au_delayed_kfree(fpair); -+out: -+ 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); -+ 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 *xino, int remount) -+{ -+ int err, skip; -+ struct dentry *parent, *cur_parent; -+ struct qstr *dname, *cur_name; -+ struct file *cur_xino; -+ struct inode *dir; -+ struct au_sbinfo *sbinfo; -+ -+ SiMustWriteLock(sb); -+ -+ err = 0; -+ sbinfo = au_sbi(sb); -+ parent = dget_parent(xino->file->f_path.dentry); -+ if (remount) { -+ skip = 0; -+ dname = &xino->file->f_path.dentry->d_name; -+ cur_xino = sbinfo->si_xib; -+ if (cur_xino) { -+ cur_parent = dget_parent(cur_xino->f_path.dentry); -+ cur_name = &cur_xino->f_path.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); -+ dir = d_inode(parent); -+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); -+ /* mnt_want_write() is unnecessary here */ -+ err = au_xino_set_xib(sb, xino->file); -+ if (!err) -+ err = au_xigen_set(sb, xino->file); -+ if (!err) -+ err = au_xino_set_br(sb, xino->file); -+ mutex_unlock(&dir->i_mutex); -+ if (!err) -+ goto out; /* success */ -+ -+ /* reset all */ -+ AuIOErr("failed creating xino(%d).\n", err); -+ au_xigen_clr(sb); -+ xino_clear_xib(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); -+ if (!IS_ERR(file)) -+ au_xino_brid_set(sb, br->br_id); -+ } -+ au_delayed_free_page((unsigned long)page); -+ } else { -+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/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); -+ } -+ if (!IS_ERR(file)) -+ au_xino_brid_set(sb, -1); -+ } -+ -+out: -+ return file; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 --git a/fs/dcache.c b/fs/dcache.c -index 7b8feb6..eb2cc03 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1159,7 +1159,7 @@ enum d_walk_ret { - * - * The @enter() and @finish() 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 *), - void (*finish)(void *)) - { -@@ -1264,6 +1264,7 @@ rename_retry: - seq = 1; - goto again; - } -+EXPORT_SYMBOL_GPL(d_walk); - - /* - * Search for at least 1 mount point in the dentry's subdirs. -diff --git a/fs/exec.c b/fs/exec.c -index 3a6de10..aa7efe4 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -104,6 +104,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 --git a/fs/fcntl.c b/fs/fcntl.c -index ee85cd4..8abb9f8 100644 ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -29,7 +29,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; -@@ -59,6 +59,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) - - 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; - -@@ -79,6 +81,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) - out: - return error; - } -+EXPORT_SYMBOL_GPL(setfl); - - static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, - int force) -diff --git a/fs/file_table.c b/fs/file_table.c -index ad17e05..ae9f267 100644 ---- a/fs/file_table.c -+++ b/fs/file_table.c -@@ -147,6 +147,7 @@ over: - } - return ERR_PTR(-ENFILE); - } -+EXPORT_SYMBOL_GPL(get_empty_filp); - - /** - * alloc_file - allocate and initialize a 'struct file' -@@ -258,6 +259,7 @@ void flush_delayed_fput(void) - { - delayed_fput(NULL); - } -+EXPORT_SYMBOL_GPL(flush_delayed_fput); - - static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput); - -@@ -300,6 +302,7 @@ void __fput_sync(struct file *file) - } - - EXPORT_SYMBOL(fput); -+EXPORT_SYMBOL_GPL(__fput_sync); - - void put_filp(struct file *file) - { -@@ -308,6 +311,7 @@ void put_filp(struct file *file) - file_free(file); - } - } -+EXPORT_SYMBOL_GPL(put_filp); - - void __init files_init(void) - { -diff --git a/fs/inode.c b/fs/inode.c -index b0edef5..c76d850 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1584,7 +1584,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 timespec *time, int flags) -+int update_time(struct inode *inode, struct timespec *time, int flags) - { - int (*update_time)(struct inode *, struct timespec *, int); - -@@ -1593,6 +1593,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) - - return update_time(inode, time, flags); - } -+EXPORT_SYMBOL_GPL(update_time); - - /** - * touch_atime - update the access time -diff --git a/fs/namespace.c b/fs/namespace.c -index da98a1b..2952dd6 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -463,6 +463,7 @@ void __mnt_drop_write(struct vfsmount *mnt) - mnt_dec_writers(real_mount(mnt)); - preempt_enable(); - } -+EXPORT_SYMBOL_GPL(__mnt_drop_write); - - /** - * mnt_drop_write - give up write access to a mount -@@ -1828,6 +1829,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, - } - return 0; - } -+EXPORT_SYMBOL_GPL(iterate_mounts); - - static void cleanup_group_ids(struct mount *mnt, struct mount *end) - { -diff --git a/fs/notify/group.c b/fs/notify/group.c -index 18eb30c..f3ece77 100644 ---- a/fs/notify/group.c -+++ b/fs/notify/group.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include "fsnotify.h" -@@ -91,6 +92,7 @@ void fsnotify_get_group(struct fsnotify_group *group) - { - atomic_inc(&group->refcnt); - } -+EXPORT_SYMBOL_GPL(fsnotify_get_group); - - /* - * Drop a reference to a group. Free it if it's through. -@@ -100,6 +102,7 @@ void fsnotify_put_group(struct fsnotify_group *group) - if (atomic_dec_and_test(&group->refcnt)) - fsnotify_final_destroy_group(group); - } -+EXPORT_SYMBOL_GPL(fsnotify_put_group); - - /* - * Create a new fsnotify_group and hold a reference for the group returned. -@@ -128,6 +131,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) - - return group; - } -+EXPORT_SYMBOL_GPL(fsnotify_alloc_group); - - int fsnotify_fasync(int fd, struct file *file, int on) - { -diff --git a/fs/notify/mark.c b/fs/notify/mark.c -index fc0df44..8175f3c 100644 ---- a/fs/notify/mark.c -+++ b/fs/notify/mark.c -@@ -109,6 +109,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) - mark->free_mark(mark); - } - } -+EXPORT_SYMBOL_GPL(fsnotify_put_mark); - - /* Calculate mask of events for a list of marks */ - u32 fsnotify_recalc_mask(struct hlist_head *head) -@@ -208,6 +209,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, - mutex_unlock(&group->mark_mutex); - fsnotify_free_mark(mark); - } -+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark); - - void fsnotify_destroy_marks(struct hlist_head *head, spinlock_t *lock) - { -@@ -392,6 +394,7 @@ err: - - return ret; - } -+EXPORT_SYMBOL_GPL(fsnotify_add_mark); - - int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, - struct inode *inode, struct vfsmount *mnt, int allow_dups) -@@ -492,6 +495,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, - atomic_set(&mark->refcnt, 1); - mark->free_mark = free_mark; - } -+EXPORT_SYMBOL_GPL(fsnotify_init_mark); - - static int fsnotify_mark_destroy(void *ignored) - { -diff --git a/fs/open.c b/fs/open.c -index 157b994..f8898b4 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, - mutex_unlock(&dentry->d_inode->i_mutex); - return ret; - } -+EXPORT_SYMBOL_GPL(do_truncate); - - long vfs_truncate(struct path *path, loff_t length) - { -@@ -678,6 +679,7 @@ int open_check_o_direct(struct file *f) - } - return 0; - } -+EXPORT_SYMBOL_GPL(open_check_o_direct); - - static int do_dentry_open(struct file *f, - struct inode *inode, -diff --git a/fs/proc/base.c b/fs/proc/base.c -index 8d39532..5790c82 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -1918,7 +1918,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path) - down_read(&mm->mmap_sem); - 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 --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index f8595e8..cb8eda0 100644 ---- a/fs/proc/nommu.c -+++ b/fs/proc/nommu.c -@@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) - 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 --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index bd58857..a5fc26a 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -337,7 +337,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) - 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; -@@ -1585,7 +1588,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) - 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 mm_walk walk = { - .hugetlb_entry = gather_hugetlb_stats, -diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index faacb0c..17b43be 100644 ---- a/fs/proc/task_nommu.c -+++ b/fs/proc/task_nommu.c -@@ -163,7 +163,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, - 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 --git a/fs/read_write.c b/fs/read_write.c -index 819ef3f..0a28933 100644 ---- a/fs/read_write.c -+++ b/fs/read_write.c -@@ -494,6 +494,30 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count, - } - EXPORT_SYMBOL(__vfs_write); - -+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); -+} -+EXPORT_SYMBOL_GPL(vfs_readf); -+ -+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); -+} -+EXPORT_SYMBOL_GPL(vfs_writef); -+ - ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos) - { - mm_segment_t old_fs; -diff --git a/fs/splice.c b/fs/splice.c -index 0f77e96..22d18ed 100644 ---- a/fs/splice.c -+++ b/fs/splice.c -@@ -1113,8 +1113,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); -@@ -1126,13 +1126,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - - 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. - */ --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); -@@ -1152,6 +1153,7 @@ static long do_splice_to(struct file *in, loff_t *ppos, - - 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 --git a/fs/sync.c b/fs/sync.c -index dd5d171..cd284a8 100644 ---- a/fs/sync.c -+++ b/fs/sync.c -@@ -27,7 +27,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); -@@ -38,6 +38,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) - 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 --git a/fs/xattr.c b/fs/xattr.c -index 9b932b9..0c317c4 100644 ---- a/fs/xattr.c -+++ b/fs/xattr.c -@@ -207,6 +207,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, - *xattr_value = value; - return error; - } -+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); - - /* Compare an extended attribute value with the given value */ - int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, -diff --git a/include/linux/file.h b/include/linux/file.h -index f87d308..9a290b3 100644 ---- a/include/linux/file.h -+++ b/include/linux/file.h -@@ -19,6 +19,7 @@ struct dentry; - struct path; - extern struct file *alloc_file(struct path *, fmode_t mode, - const struct file_operations *fop); -+extern struct file *get_empty_filp(void); - - static inline void fput_light(struct file *file, int fput_needed) - { -diff --git a/include/linux/fs.h b/include/linux/fs.h -index e1a1237..a5b6cb2 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1269,6 +1269,7 @@ extern void fasync_free(struct fasync_struct *); - /* 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 void f_setown(struct file *filp, unsigned long arg, int force); - extern void f_delown(struct file *filp); -@@ -1655,6 +1656,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); -@@ -1708,6 +1710,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - 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_write(struct file *, const char __user *, size_t, loff_t *); - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); -@@ -2057,6 +2065,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 timespec *, int); -+extern int update_time(struct inode *, struct timespec *, int); - - /* /sys/fs */ - extern struct kobject *fs_kobj; -@@ -2332,6 +2341,7 @@ static inline int sb_is_blkdev_sb(struct super_block *sb) - return 0; - } - #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 --git a/include/linux/mm.h b/include/linux/mm.h -index f8a7297..be00303 100644 ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -1197,6 +1197,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, - } - #endif - -+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, int write); - extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, - void *buf, int len, int write); -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index af25bc1..51ef1ba 100644 ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -272,6 +272,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 -@@ -353,6 +354,7 @@ struct vm_area_struct { - unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE - units, *not* PAGE_CACHE_SIZE */ - 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) */ - - #ifndef CONFIG_MMU -diff --git a/include/linux/splice.h b/include/linux/splice.h -index da2751d..2e0fca6 100644 ---- a/include/linux/splice.h -+++ b/include/linux/splice.h -@@ -83,4 +83,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); - extern void spd_release_page(struct splice_pipe_desc *, unsigned int); - - extern const struct pipe_buf_operations page_cache_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 --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild -index ebd10e6..32152e7 100644 ---- a/include/uapi/linux/Kbuild -+++ b/include/uapi/linux/Kbuild -@@ -59,6 +59,7 @@ header-y += atmsvc.h - header-y += atm_tcp.h - header-y += atm_zatm.h - header-y += audit.h -+header-y += aufs_type.h - header-y += auto_fs4.h - header-y += auto_fs.h - header-y += auxvec.h -diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h -new file mode 100644 -index 0000000..72e69b1 ---- /dev/null -+++ b/include/uapi/linux/aufs_type.h -@@ -0,0 +1,419 @@ -+/* -+ * Copyright (C) 2005-2017 Junjiro R. Okajima -+ * -+ * This program, aufs is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#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 "4.4-20170220" -+ -+/* 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 -+ -+#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 -+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) -+#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); -+ -+/* ---------------------------------------------------------------------- */ -+ -+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 --git a/kernel/fork.c b/kernel/fork.c -index c85efa7..d4b0e6f 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -465,7 +465,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) - 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 --git a/kernel/task_work.c b/kernel/task_work.c -index 53fa971..bce3211 100644 ---- a/kernel/task_work.c -+++ b/kernel/task_work.c -@@ -118,3 +118,4 @@ void task_work_run(void) - } while (work); - } - } -+EXPORT_SYMBOL_GPL(task_work_run); -diff --git a/mm/Makefile b/mm/Makefile -index 2ed4319..e3a53f5 100644 ---- a/mm/Makefile -+++ b/mm/Makefile -@@ -21,7 +21,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ - 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 $(mmu-y) -+ prfile.o debug.o $(mmu-y) - - obj-y += init-mm.o - -diff --git a/mm/filemap.c b/mm/filemap.c -index c33c31d..797c76b 100644 ---- a/mm/filemap.c -+++ b/mm/filemap.c -@@ -2140,7 +2140,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) - int ret = VM_FAULT_LOCKED; - - sb_start_pagefault(inode->i_sb); -- file_update_time(vma->vm_file); -+ vma_file_update_time(vma); - lock_page(page); - if (page->mapping != inode->i_mapping) { - unlock_page(page); -diff --git a/mm/memory.c b/mm/memory.c -index 76dcee3..278c33c 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -2075,7 +2075,7 @@ static inline int wp_page_reuse(struct mm_struct *mm, - } - - if (!page_mkwrite) -- file_update_time(vma->vm_file); -+ vma_file_update_time(vma); - } - - return VM_FAULT_WRITE; -diff --git a/mm/mmap.c b/mm/mmap.c -index a089cca..9017b6e 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -287,7 +287,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *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)); - kmem_cache_free(vm_area_cachep, vma); - return next; -@@ -903,7 +903,7 @@ again: remove_next = 1 + (end > next->vm_end); - 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); -@@ -1706,8 +1706,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); -@@ -2504,7 +2504,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, - 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); -@@ -2523,7 +2523,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, - 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)); -@@ -2666,7 +2666,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - 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.txt.\n", -@@ -2734,10 +2734,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - } - } - -- 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); -+ 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) -@@ -3007,7 +3024,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, - 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 --git a/mm/nommu.c b/mm/nommu.c -index 92be862..29179f7 100644 ---- a/mm/nommu.c -+++ b/mm/nommu.c -@@ -671,7 +671,7 @@ static void __put_nommu_region(struct vm_region *region) - 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 */ -@@ -829,7 +829,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *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); - put_nommu_region(vma->vm_region); - kmem_cache_free(vm_area_cachep, vma); - } -@@ -1355,7 +1355,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; -@@ -1430,10 +1430,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); - kmem_cache_free(vm_area_cachep, vma); - return ret; - -diff --git a/mm/prfile.c b/mm/prfile.c -new file mode 100644 -index 0000000..b323b8a ---- /dev/null -+++ b/mm/prfile.c -@@ -0,0 +1,86 @@ -+/* -+ * Mainly for aufs which mmap(2) diffrent 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 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, %s\n", func, line, func2, -+ f ? (char *)f->f_path.dentry->d_name.name : "(null)"); -+#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/security/commoncap.c b/security/commoncap.c -index 7fa251a..b965cb1 100644 ---- a/security/commoncap.c -+++ b/security/commoncap.c -@@ -1069,12 +1069,14 @@ int cap_mmap_addr(unsigned long addr) - } - return ret; - } -+EXPORT_SYMBOL_GPL(cap_mmap_addr); - - int cap_mmap_file(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) - { - return 0; - } -+EXPORT_SYMBOL_GPL(cap_mmap_file); - - #ifdef CONFIG_SECURITY - -diff --git a/security/device_cgroup.c b/security/device_cgroup.c -index 03c1652..f88c84b 100644 ---- a/security/device_cgroup.c -+++ b/security/device_cgroup.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -849,6 +850,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask) - return __devcgroup_check_permission(type, imajor(inode), iminor(inode), - access); - } -+EXPORT_SYMBOL_GPL(__devcgroup_inode_permission); - - int devcgroup_inode_mknod(int mode, dev_t dev) - { -diff --git a/security/security.c b/security/security.c -index 46f405c..bc8514e 100644 ---- a/security/security.c -+++ b/security/security.c -@@ -433,6 +433,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry) - return 0; - return call_int_hook(path_rmdir, 0, dir, dentry); - } -+EXPORT_SYMBOL_GPL(security_path_rmdir); - - int security_path_unlink(struct path *dir, struct dentry *dentry) - { -@@ -449,6 +450,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry, - 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, struct path *new_dir, - struct dentry *new_dentry) -@@ -457,6 +459,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, - 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(struct path *old_dir, struct dentry *old_dentry, - struct path *new_dir, struct dentry *new_dentry, -@@ -484,6 +487,7 @@ int security_path_truncate(struct path *path) - return 0; - return call_int_hook(path_truncate, 0, path); - } -+EXPORT_SYMBOL_GPL(security_path_truncate); - - int security_path_chmod(struct path *path, umode_t mode) - { -@@ -491,6 +495,7 @@ int security_path_chmod(struct path *path, umode_t mode) - return 0; - return call_int_hook(path_chmod, 0, path, mode); - } -+EXPORT_SYMBOL_GPL(security_path_chmod); - - int security_path_chown(struct path *path, kuid_t uid, kgid_t gid) - { -@@ -498,6 +503,7 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid) - return 0; - return call_int_hook(path_chown, 0, path, uid, gid); - } -+EXPORT_SYMBOL_GPL(security_path_chown); - - int security_path_chroot(struct path *path) - { -@@ -583,6 +589,7 @@ int security_inode_readlink(struct dentry *dentry) - return 0; - return call_int_hook(inode_readlink, 0, dentry); - } -+EXPORT_SYMBOL_GPL(security_inode_readlink); - - int security_inode_follow_link(struct dentry *dentry, struct inode *inode, - bool rcu) -@@ -598,6 +605,7 @@ int security_inode_permission(struct inode *inode, int mask) - 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) - { -@@ -736,6 +744,7 @@ int security_file_permission(struct file *file, int mask) - - return fsnotify_perm(file, mask); - } -+EXPORT_SYMBOL_GPL(security_file_permission); - - int security_file_alloc(struct file *file) - { -@@ -795,6 +804,7 @@ int security_mmap_file(struct file *file, unsigned long prot, - return ret; - return ima_file_mmap(file, prot); - } -+EXPORT_SYMBOL_GPL(security_mmap_file); - - int security_mmap_addr(unsigned long addr) - { diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.69-70.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.69-70.patch deleted file mode 100644 index 948006ddb..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.69-70.patch +++ /dev/null @@ -1,3739 +0,0 @@ -diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt -index d9995f1f51b3..a25a99e82bb1 100644 ---- a/Documentation/arm64/tagged-pointers.txt -+++ b/Documentation/arm64/tagged-pointers.txt -@@ -11,24 +11,56 @@ in AArch64 Linux. - The kernel configures the translation tables so that translations made - via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of - the virtual address ignored by the translation hardware. This frees up --this byte for application use, with the following caveats: -+this byte for application use. - -- (1) The kernel requires that all user addresses passed to EL1 -- are tagged with tag 0x00. This means that any syscall -- parameters containing user virtual addresses *must* have -- their top byte cleared before trapping to the kernel. - -- (2) Non-zero tags are not preserved when delivering signals. -- This means that signal handlers in applications making use -- of tags cannot rely on the tag information for user virtual -- addresses being maintained for fields inside siginfo_t. -- One exception to this rule is for signals raised in response -- to watchpoint debug exceptions, where the tag information -- will be preserved. -+Passing tagged addresses to the kernel -+-------------------------------------- - -- (3) Special care should be taken when using tagged pointers, -- since it is likely that C compilers will not hazard two -- virtual addresses differing only in the upper byte. -+All interpretation of userspace memory addresses by the kernel assumes -+an address tag of 0x00. -+ -+This includes, but is not limited to, addresses found in: -+ -+ - pointer arguments to system calls, including pointers in structures -+ passed to system calls, -+ -+ - the stack pointer (sp), e.g. when interpreting it to deliver a -+ signal, -+ -+ - the frame pointer (x29) and frame records, e.g. when interpreting -+ them to generate a backtrace or call graph. -+ -+Using non-zero address tags in any of these locations may result in an -+error code being returned, a (fatal) signal being raised, or other modes -+of failure. -+ -+For these reasons, passing non-zero address tags to the kernel via -+system calls is forbidden, and using a non-zero address tag for sp is -+strongly discouraged. -+ -+Programs maintaining a frame pointer and frame records that use non-zero -+address tags may suffer impaired or inaccurate debug and profiling -+visibility. -+ -+ -+Preserving tags -+--------------- -+ -+Non-zero tags are not preserved when delivering signals. This means that -+signal handlers in applications making use of tags cannot rely on the -+tag information for user virtual addresses being maintained for fields -+inside siginfo_t. One exception to this rule is for signals raised in -+response to watchpoint debug exceptions, where the tag information will -+be preserved. - - The architecture prevents the use of a tagged PC, so the upper byte will - be set to a sign-extension of bit 55 on exception return. -+ -+ -+Other considerations -+-------------------- -+ -+Special care should be taken when using tagged pointers, since it is -+likely that C compilers will not hazard two virtual addresses differing -+only in the upper byte. -diff --git a/Makefile b/Makefile -index dc5df61ea4be..a5ecb29c6ed3 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 69 -+SUBLEVEL = 70 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c -index 6cc08166ff00..63f06a2b1f7f 100644 ---- a/arch/alpha/kernel/osf_sys.c -+++ b/arch/alpha/kernel/osf_sys.c -@@ -1188,8 +1188,10 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, - if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) - return -EFAULT; - -- err = 0; -- err |= put_user(status, ustatus); -+ err = put_user(status, ustatus); -+ if (ret < 0) -+ return err ? err : ret; -+ - err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); - err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); - err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); -diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts -index f3e2b96c06a3..0bd325c314e1 100644 ---- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts -+++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts -@@ -162,9 +162,10 @@ - }; - - adc0: adc@f8018000 { -+ atmel,adc-vref = <3300>; -+ atmel,adc-channels-used = <0xfe>; - pinctrl-0 = < - &pinctrl_adc0_adtrg -- &pinctrl_adc0_ad0 - &pinctrl_adc0_ad1 - &pinctrl_adc0_ad2 - &pinctrl_adc0_ad3 -@@ -172,8 +173,6 @@ - &pinctrl_adc0_ad5 - &pinctrl_adc0_ad6 - &pinctrl_adc0_ad7 -- &pinctrl_adc0_ad8 -- &pinctrl_adc0_ad9 - >; - status = "okay"; - }; -diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts -index ed7e1009326c..d9ee0fd817e9 100644 ---- a/arch/arm/boot/dts/tegra20-paz00.dts -+++ b/arch/arm/boot/dts/tegra20-paz00.dts -@@ -565,6 +565,7 @@ - regulator-name = "+3VS,vdd_pnl"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; -+ regulator-boot-on; - gpio = <&gpio TEGRA_GPIO(A, 4) GPIO_ACTIVE_HIGH>; - enable-active-high; - }; -diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h -index 9ea611ea69df..91ceeb7b4530 100644 ---- a/arch/arm64/include/asm/cmpxchg.h -+++ b/arch/arm64/include/asm/cmpxchg.h -@@ -49,7 +49,7 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \ - " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ - " nop\n" \ - " " #nop_lse) \ -- : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr) \ -+ : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \ - : "r" (x) \ - : cl); \ - \ -diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h -index b2ede967fe7d..d9ca1f2c0ea8 100644 ---- a/arch/arm64/include/asm/uaccess.h -+++ b/arch/arm64/include/asm/uaccess.h -@@ -92,11 +92,12 @@ static inline void set_fs(mm_segment_t fs) - */ - #define __range_ok(addr, size) \ - ({ \ -+ unsigned long __addr = (unsigned long __force)(addr); \ - unsigned long flag, roksum; \ - __chk_user_ptr(addr); \ - asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ - : "=&r" (flag), "=&r" (roksum) \ -- : "1" (addr), "Ir" (size), \ -+ : "1" (__addr), "Ir" (size), \ - "r" (current_thread_info()->addr_limit) \ - : "cc"); \ - flag; \ -diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h -index 07238b39638c..3db381205928 100644 ---- a/arch/metag/include/asm/uaccess.h -+++ b/arch/metag/include/asm/uaccess.h -@@ -28,24 +28,32 @@ - - #define segment_eq(a, b) ((a).seg == (b).seg) - --#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) --/* -- * Explicitly allow NULL pointers here. Parts of the kernel such -- * as readv/writev use access_ok to validate pointers, but want -- * to allow NULL pointers for various reasons. NULL pointers are -- * safe to allow through because the first page is not mappable on -- * Meta. -- * -- * We also wish to avoid letting user code access the system area -- * and the kernel half of the address space. -- */ --#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \ -- ((addr) > PAGE_OFFSET && \ -- (addr) < LINCORE_BASE)) -- - static inline int __access_ok(unsigned long addr, unsigned long size) - { -- return __kernel_ok || !__user_bad(addr, size); -+ /* -+ * Allow access to the user mapped memory area, but not the system area -+ * before it. The check extends to the top of the address space when -+ * kernel access is allowed (there's no real reason to user copy to the -+ * system area in any case). -+ */ -+ if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg && -+ size <= get_fs().seg - addr)) -+ return true; -+ /* -+ * Explicitly allow NULL pointers here. Parts of the kernel such -+ * as readv/writev use access_ok to validate pointers, but want -+ * to allow NULL pointers for various reasons. NULL pointers are -+ * safe to allow through because the first page is not mappable on -+ * Meta. -+ */ -+ if (!addr) -+ return true; -+ /* Allow access to core code memory area... */ -+ if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT && -+ size <= LINCORE_CODE_LIMIT + 1 - addr) -+ return true; -+ /* ... but no other areas. */ -+ return false; - } - - #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ -@@ -186,8 +194,13 @@ do { \ - extern long __must_check __strncpy_from_user(char *dst, const char __user *src, - long count); - --#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count) -- -+static inline long -+strncpy_from_user(char *dst, const char __user *src, long count) -+{ -+ if (!access_ok(VERIFY_READ, src, 1)) -+ return -EFAULT; -+ return __strncpy_from_user(dst, src, count); -+} - /* - * Return the size of a string (including the ending 0) - * -diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S -index 488e6314f993..5cc93f0b52ca 100644 ---- a/arch/powerpc/kernel/exceptions-64e.S -+++ b/arch/powerpc/kernel/exceptions-64e.S -@@ -735,8 +735,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) - andis. r15,r14,(DBSR_IC|DBSR_BT)@h - beq+ 1f - -+#ifdef CONFIG_RELOCATABLE -+ ld r15,PACATOC(r13) -+ ld r14,interrupt_base_book3e@got(r15) -+ ld r15,__end_interrupts@got(r15) -+#else - LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) - LOAD_REG_IMMEDIATE(r15,__end_interrupts) -+#endif - cmpld cr0,r10,r14 - cmpld cr1,r10,r15 - blt+ cr0,1f -@@ -799,8 +805,14 @@ kernel_dbg_exc: - andis. r15,r14,(DBSR_IC|DBSR_BT)@h - beq+ 1f - -+#ifdef CONFIG_RELOCATABLE -+ ld r15,PACATOC(r13) -+ ld r14,interrupt_base_book3e@got(r15) -+ ld r15,__end_interrupts@got(r15) -+#else - LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) - LOAD_REG_IMMEDIATE(r15,__end_interrupts) -+#endif - cmpld cr0,r10,r14 - cmpld cr1,r10,r15 - blt+ cr0,1f -diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c -index b2eb4686bd8f..da3c4c3f4ec8 100644 ---- a/arch/powerpc/kernel/mce.c -+++ b/arch/powerpc/kernel/mce.c -@@ -204,6 +204,8 @@ static void machine_check_process_queued_event(struct irq_work *work) - { - int index; - -+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); -+ - /* - * For now just print it to console. - * TODO: log this error event to FSP or nvram. -diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c -index 37de90f8a845..e4dcb0a43e3f 100644 ---- a/arch/powerpc/kernel/traps.c -+++ b/arch/powerpc/kernel/traps.c -@@ -297,8 +297,6 @@ long machine_check_early(struct pt_regs *regs) - - __this_cpu_inc(irq_stat.mce_exceptions); - -- add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); -- - if (cur_cpu_spec && cur_cpu_spec->machine_check_early) - handled = cur_cpu_spec->machine_check_early(regs); - return handled; -@@ -704,6 +702,8 @@ void machine_check_exception(struct pt_regs *regs) - - __this_cpu_inc(irq_stat.mce_exceptions); - -+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); -+ - /* See if any machine dependent calls. In theory, we would want - * to call the CPU first, and call the ppc_md. one if the CPU - * one returns a positive number. However there is existing code -diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c -index f244dcb4f2cf..96536c969c9c 100644 ---- a/arch/powerpc/platforms/pseries/dlpar.c -+++ b/arch/powerpc/platforms/pseries/dlpar.c -@@ -280,7 +280,6 @@ int dlpar_detach_node(struct device_node *dn) - if (rc) - return rc; - -- of_node_put(dn); /* Must decrement the refcount */ - return 0; - } - -diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c -index f7c3a61040bd..df4685905015 100644 ---- a/arch/s390/kernel/crash_dump.c -+++ b/arch/s390/kernel/crash_dump.c -@@ -464,6 +464,20 @@ static void *nt_vmcoreinfo(void *ptr) - } - - /* -+ * Initialize final note (needed for /proc/vmcore code) -+ */ -+static void *nt_final(void *ptr) -+{ -+ Elf64_Nhdr *note; -+ -+ note = (Elf64_Nhdr *) ptr; -+ note->n_namesz = 0; -+ note->n_descsz = 0; -+ note->n_type = 0; -+ return PTR_ADD(ptr, sizeof(Elf64_Nhdr)); -+} -+ -+/* - * Initialize ELF header (new kernel) - */ - static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt) -@@ -553,6 +567,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) - ptr = fill_cpu_elf_notes(ptr, &sa_ext->sa, sa_ext->vx_regs); - } - ptr = nt_vmcoreinfo(ptr); -+ ptr = nt_final(ptr); - memset(phdr, 0, sizeof(*phdr)); - phdr->p_type = PT_NOTE; - phdr->p_offset = notes_offset; -diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S -index 424e6809ad07..7460df3eec6b 100644 ---- a/arch/s390/kernel/entry.S -+++ b/arch/s390/kernel/entry.S -@@ -308,6 +308,7 @@ ENTRY(system_call) - lg %r14,__LC_VDSO_PER_CPU - lmg %r0,%r10,__PT_R0(%r11) - mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) -+.Lsysc_exit_timer: - stpt __LC_EXIT_TIMER - mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER - lmg %r11,%r15,__PT_R11(%r11) -@@ -593,6 +594,7 @@ ENTRY(io_int_handler) - lg %r14,__LC_VDSO_PER_CPU - lmg %r0,%r10,__PT_R0(%r11) - mvc __LC_RETURN_PSW(16),__PT_PSW(%r11) -+.Lio_exit_timer: - stpt __LC_EXIT_TIMER - mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER - lmg %r11,%r15,__PT_R11(%r11) -@@ -1118,15 +1120,23 @@ cleanup_critical: - br %r14 - - .Lcleanup_sysc_restore: -+ # check if stpt has been executed - clg %r9,BASED(.Lcleanup_sysc_restore_insn) -+ jh 0f -+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER -+ cghi %r11,__LC_SAVE_AREA_ASYNC - je 0f -+ mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER -+0: clg %r9,BASED(.Lcleanup_sysc_restore_insn+8) -+ je 1f - lg %r9,24(%r11) # get saved pointer to pt_regs - mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) - mvc 0(64,%r11),__PT_R8(%r9) - lmg %r0,%r7,__PT_R0(%r9) --0: lmg %r8,%r9,__LC_RETURN_PSW -+1: lmg %r8,%r9,__LC_RETURN_PSW - br %r14 - .Lcleanup_sysc_restore_insn: -+ .quad .Lsysc_exit_timer - .quad .Lsysc_done - 4 - - .Lcleanup_io_tif: -@@ -1134,15 +1144,20 @@ cleanup_critical: - br %r14 - - .Lcleanup_io_restore: -+ # check if stpt has been executed - clg %r9,BASED(.Lcleanup_io_restore_insn) -- je 0f -+ jh 0f -+ mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER -+0: clg %r9,BASED(.Lcleanup_io_restore_insn+8) -+ je 1f - lg %r9,24(%r11) # get saved r11 pointer to pt_regs - mvc __LC_RETURN_PSW(16),__PT_PSW(%r9) - mvc 0(64,%r11),__PT_R8(%r9) - lmg %r0,%r7,__PT_R0(%r9) --0: lmg %r8,%r9,__LC_RETURN_PSW -+1: lmg %r8,%r9,__LC_RETURN_PSW - br %r14 - .Lcleanup_io_restore_insn: -+ .quad .Lio_exit_timer - .quad .Lio_done - 4 - - .Lcleanup_idle: -diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c -index be39b5fde4b9..1011c05b1bd5 100644 ---- a/arch/x86/kernel/fpu/init.c -+++ b/arch/x86/kernel/fpu/init.c -@@ -96,6 +96,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c) - * Boot time FPU feature detection code: - */ - unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; -+EXPORT_SYMBOL_GPL(mxcsr_feature_mask); - - static void __init fpu__init_system_mxcsr(void) - { -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 281899da19d4..ae2b9cd358f2 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -3140,11 +3140,14 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, - } - } - -+#define XSAVE_MXCSR_OFFSET 24 -+ - static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, - struct kvm_xsave *guest_xsave) - { - u64 xstate_bv = - *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)]; -+ u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)]; - - if (cpu_has_xsave) { - /* -@@ -3152,11 +3155,13 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, - * CPUID leaf 0xD, index 0, EDX:EAX. This is for compatibility - * with old userspace. - */ -- if (xstate_bv & ~kvm_supported_xcr0()) -+ if (xstate_bv & ~kvm_supported_xcr0() || -+ mxcsr & ~mxcsr_feature_mask) - return -EINVAL; - load_xsave(vcpu, (u8 *)guest_xsave->region); - } else { -- if (xstate_bv & ~XFEATURE_MASK_FPSSE) -+ if (xstate_bv & ~XFEATURE_MASK_FPSSE || -+ mxcsr & ~mxcsr_feature_mask) - return -EINVAL; - memcpy(&vcpu->arch.guest_fpu.state.fxsave, - guest_xsave->region, sizeof(struct fxregs_state)); -@@ -4603,16 +4608,20 @@ emul_write: - - static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) - { -- /* TODO: String I/O for in kernel device */ -- int r; -+ int r = 0, i; - -- if (vcpu->arch.pio.in) -- r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, -- vcpu->arch.pio.size, pd); -- else -- r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, -- vcpu->arch.pio.port, vcpu->arch.pio.size, -- pd); -+ for (i = 0; i < vcpu->arch.pio.count; i++) { -+ if (vcpu->arch.pio.in) -+ r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, -+ vcpu->arch.pio.size, pd); -+ else -+ r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, -+ vcpu->arch.pio.port, vcpu->arch.pio.size, -+ pd); -+ if (r) -+ break; -+ pd += vcpu->arch.pio.size; -+ } - return r; - } - -@@ -4650,6 +4659,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, - if (vcpu->arch.pio.count) - goto data_avail; - -+ memset(vcpu->arch.pio_data, 0, size * count); -+ - ret = emulator_pio_in_out(vcpu, size, port, val, count, true); - if (ret) { - data_avail: -diff --git a/drivers/char/lp.c b/drivers/char/lp.c -index c4094c4e22c1..34ef474a3923 100644 ---- a/drivers/char/lp.c -+++ b/drivers/char/lp.c -@@ -859,7 +859,11 @@ static int __init lp_setup (char *str) - } else if (!strcmp(str, "auto")) { - parport_nr[0] = LP_PARPORT_AUTO; - } else if (!strcmp(str, "none")) { -- parport_nr[parport_ptr++] = LP_PARPORT_NONE; -+ if (parport_ptr < LP_NO) -+ parport_nr[parport_ptr++] = LP_PARPORT_NONE; -+ else -+ printk(KERN_INFO "lp: too many ports, %s ignored.\n", -+ str); - } else if (!strcmp(str, "reset")) { - reset = 1; - } -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index e901463d4972..0975d23031ea 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -343,6 +343,11 @@ static const struct vm_operations_struct mmap_mem_ops = { - static int mmap_mem(struct file *file, struct vm_area_struct *vma) - { - size_t size = vma->vm_end - vma->vm_start; -+ phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; -+ -+ /* It's illegal to wrap around the end of the physical address space. */ -+ if (offset + (phys_addr_t)size < offset) -+ return -EINVAL; - - if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) - return -EINVAL; -diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c -index 2b21398c3adc..35308dfff754 100644 ---- a/drivers/char/tpm/tpm_crb.c -+++ b/drivers/char/tpm/tpm_crb.c -@@ -118,8 +118,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) - - memcpy_fromio(buf, priv->rsp, 6); - expected = be32_to_cpup((__be32 *) &buf[2]); -- -- if (expected > count) -+ if (expected > count || expected < 6) - return -EIO; - - memcpy_fromio(&buf[6], &priv->rsp[6], expected - 6); -diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c -index 5b261adb4b69..3a25da4a6e60 100644 ---- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c -@@ -1126,23 +1126,10 @@ static u32 dce_v10_0_latency_watermark(struct dce10_wm_params *wm) - a.full = dfixed_const(available_bandwidth); - b.full = dfixed_const(wm->num_heads); - a.full = dfixed_div(a, b); -+ tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); -+ tmp = min(dfixed_trunc(a), tmp); - -- b.full = dfixed_const(mc_latency + 512); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(b, c); -- -- c.full = dfixed_const(dmif_size); -- b.full = dfixed_div(c, b); -- -- tmp = min(dfixed_trunc(a), dfixed_trunc(b)); -- -- b.full = dfixed_const(1000); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(c, b); -- c.full = dfixed_const(wm->bytes_per_pixel); -- b.full = dfixed_mul(b, c); -- -- lb_fill_bw = min(tmp, dfixed_trunc(b)); -+ lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); - - a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); - b.full = dfixed_const(1000); -@@ -1250,14 +1237,14 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, - { - struct drm_display_mode *mode = &amdgpu_crtc->base.mode; - struct dce10_wm_params wm_low, wm_high; -- u32 pixel_period; -+ u32 active_time; - u32 line_time = 0; - u32 latency_watermark_a = 0, latency_watermark_b = 0; - u32 tmp, wm_mask, lb_vblank_lead_lines = 0; - - if (amdgpu_crtc->base.enabled && num_heads && mode) { -- pixel_period = 1000000 / (u32)mode->clock; -- line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); -+ active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -+ line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); - - /* watermark for high clocks */ - if (adev->pm.dpm_enabled) { -@@ -1272,7 +1259,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, - - wm_high.disp_clk = mode->clock; - wm_high.src_width = mode->crtc_hdisplay; -- wm_high.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_high.active_time = active_time; - wm_high.blank_time = line_time - wm_high.active_time; - wm_high.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -@@ -1311,7 +1298,7 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev, - - wm_low.disp_clk = mode->clock; - wm_low.src_width = mode->crtc_hdisplay; -- wm_low.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_low.active_time = active_time; - wm_low.blank_time = line_time - wm_low.active_time; - wm_low.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c -index 267749a94c5a..d6d3cda77762 100644 ---- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c -@@ -1114,23 +1114,10 @@ static u32 dce_v11_0_latency_watermark(struct dce10_wm_params *wm) - a.full = dfixed_const(available_bandwidth); - b.full = dfixed_const(wm->num_heads); - a.full = dfixed_div(a, b); -+ tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); -+ tmp = min(dfixed_trunc(a), tmp); - -- b.full = dfixed_const(mc_latency + 512); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(b, c); -- -- c.full = dfixed_const(dmif_size); -- b.full = dfixed_div(c, b); -- -- tmp = min(dfixed_trunc(a), dfixed_trunc(b)); -- -- b.full = dfixed_const(1000); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(c, b); -- c.full = dfixed_const(wm->bytes_per_pixel); -- b.full = dfixed_mul(b, c); -- -- lb_fill_bw = min(tmp, dfixed_trunc(b)); -+ lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); - - a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); - b.full = dfixed_const(1000); -@@ -1238,14 +1225,14 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, - { - struct drm_display_mode *mode = &amdgpu_crtc->base.mode; - struct dce10_wm_params wm_low, wm_high; -- u32 pixel_period; -+ u32 active_time; - u32 line_time = 0; - u32 latency_watermark_a = 0, latency_watermark_b = 0; - u32 tmp, wm_mask, lb_vblank_lead_lines = 0; - - if (amdgpu_crtc->base.enabled && num_heads && mode) { -- pixel_period = 1000000 / (u32)mode->clock; -- line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); -+ active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -+ line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); - - /* watermark for high clocks */ - if (adev->pm.dpm_enabled) { -@@ -1260,7 +1247,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, - - wm_high.disp_clk = mode->clock; - wm_high.src_width = mode->crtc_hdisplay; -- wm_high.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_high.active_time = active_time; - wm_high.blank_time = line_time - wm_high.active_time; - wm_high.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -@@ -1299,7 +1286,7 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev, - - wm_low.disp_clk = mode->clock; - wm_low.src_width = mode->crtc_hdisplay; -- wm_low.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_low.active_time = active_time; - wm_low.blank_time = line_time - wm_low.active_time; - wm_low.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c -index 9b4dcf76ce6c..d6e51d4b04f0 100644 ---- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c -+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c -@@ -1096,23 +1096,10 @@ static u32 dce_v8_0_latency_watermark(struct dce8_wm_params *wm) - a.full = dfixed_const(available_bandwidth); - b.full = dfixed_const(wm->num_heads); - a.full = dfixed_div(a, b); -+ tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); -+ tmp = min(dfixed_trunc(a), tmp); - -- b.full = dfixed_const(mc_latency + 512); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(b, c); -- -- c.full = dfixed_const(dmif_size); -- b.full = dfixed_div(c, b); -- -- tmp = min(dfixed_trunc(a), dfixed_trunc(b)); -- -- b.full = dfixed_const(1000); -- c.full = dfixed_const(wm->disp_clk); -- b.full = dfixed_div(c, b); -- c.full = dfixed_const(wm->bytes_per_pixel); -- b.full = dfixed_mul(b, c); -- -- lb_fill_bw = min(tmp, dfixed_trunc(b)); -+ lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); - - a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); - b.full = dfixed_const(1000); -@@ -1220,14 +1207,14 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, - { - struct drm_display_mode *mode = &amdgpu_crtc->base.mode; - struct dce8_wm_params wm_low, wm_high; -- u32 pixel_period; -+ u32 active_time; - u32 line_time = 0; - u32 latency_watermark_a = 0, latency_watermark_b = 0; - u32 tmp, wm_mask, lb_vblank_lead_lines = 0; - - if (amdgpu_crtc->base.enabled && num_heads && mode) { -- pixel_period = 1000000 / (u32)mode->clock; -- line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); -+ active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -+ line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); - - /* watermark for high clocks */ - if (adev->pm.dpm_enabled) { -@@ -1242,7 +1229,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, - - wm_high.disp_clk = mode->clock; - wm_high.src_width = mode->crtc_hdisplay; -- wm_high.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_high.active_time = active_time; - wm_high.blank_time = line_time - wm_high.active_time; - wm_high.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -@@ -1281,7 +1268,7 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev, - - wm_low.disp_clk = mode->clock; - wm_low.src_width = mode->crtc_hdisplay; -- wm_low.active_time = mode->crtc_hdisplay * pixel_period; -+ wm_low.active_time = active_time; - wm_low.blank_time = line_time - wm_low.active_time; - wm_low.interlaced = false; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) -diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c -index cc1e16fd7e76..c0106fd9fae9 100644 ---- a/drivers/gpu/drm/drm_edid.c -+++ b/drivers/gpu/drm/drm_edid.c -@@ -75,6 +75,8 @@ - #define EDID_QUIRK_FORCE_12BPC (1 << 9) - /* Force 6bpc */ - #define EDID_QUIRK_FORCE_6BPC (1 << 10) -+/* Force 10bpc */ -+#define EDID_QUIRK_FORCE_10BPC (1 << 11) - - struct detailed_mode_closure { - struct drm_connector *connector; -@@ -117,6 +119,9 @@ static struct edid_quirk { - { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | - EDID_QUIRK_DETAILED_IN_CM }, - -+ /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ -+ { "LGD", 764, EDID_QUIRK_FORCE_10BPC }, -+ - /* LG Philips LCD LP154W01-A5 */ - { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, - { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, -@@ -3834,6 +3839,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) - if (quirks & EDID_QUIRK_FORCE_8BPC) - connector->display_info.bpc = 8; - -+ if (quirks & EDID_QUIRK_FORCE_10BPC) -+ connector->display_info.bpc = 10; -+ - if (quirks & EDID_QUIRK_FORCE_12BPC) - connector->display_info.bpc = 12; - -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c -index 949dc6101a58..7c0b58613747 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c -@@ -130,7 +130,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) - poll = false; - } - -- if (list_empty(&therm->alarm.head) && poll) -+ if (poll) - nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm); - spin_unlock_irqrestore(&therm->lock, flags); - -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c -index 91198d79393a..e2feccec25f5 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c -@@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) - spin_unlock_irqrestore(&fan->lock, flags); - - /* schedule next fan update, if not at target speed already */ -- if (list_empty(&fan->alarm.head) && target != duty) { -+ if (target != duty) { - u16 bump_period = fan->bios.bump_period; - u16 slow_down_period = fan->bios.slow_down_period; - u64 delay; -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c -index 59701b7a6597..ff9fbe7950e5 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c -@@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent) - duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff); - nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - -- if (list_empty(&fan->alarm.head) && percent != (duty * 100)) { -+ if (percent != (duty * 100)) { - u64 next_change = (percent * fan->period_us) / 100; - if (!duty) - next_change = fan->period_us - next_change; -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c -index b9703c02d8ca..9a79e91fdfdc 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c -@@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm) - spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); - - /* schedule the next poll in one second */ -- if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head)) -+ if (therm->func->temp_get(therm) >= 0) - nvkm_timer_alarm(tmr, 1000000000ULL, alarm); - } - -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -index d4dae1f12d62..79fcdb43e174 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -@@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) - unsigned long flags; - LIST_HEAD(exec); - -- /* move any due alarms off the pending list */ -+ /* Process pending alarms. */ - spin_lock_irqsave(&tmr->lock, flags); - list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) { -- if (alarm->timestamp <= nvkm_timer_read(tmr)) -- list_move_tail(&alarm->head, &exec); -+ /* Have we hit the earliest alarm that hasn't gone off? */ -+ if (alarm->timestamp > nvkm_timer_read(tmr)) { -+ /* Schedule it. If we didn't race, we're done. */ -+ tmr->func->alarm_init(tmr, alarm->timestamp); -+ if (alarm->timestamp > nvkm_timer_read(tmr)) -+ break; -+ } -+ -+ /* Move to completed list. We'll drop the lock before -+ * executing the callback so it can reschedule itself. -+ */ -+ list_move_tail(&alarm->head, &exec); - } - -- /* reschedule interrupt for next alarm time */ -- if (!list_empty(&tmr->alarms)) { -- alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head); -- tmr->func->alarm_init(tmr, alarm->timestamp); -- } else { -+ /* Shut down interrupt if no more pending alarms. */ -+ if (list_empty(&tmr->alarms)) - tmr->func->alarm_fini(tmr); -- } - spin_unlock_irqrestore(&tmr->lock, flags); - -- /* execute any pending alarm handlers */ -+ /* Execute completed callbacks. */ - list_for_each_entry_safe(alarm, atemp, &exec, head) { - list_del_init(&alarm->head); - alarm->func(alarm); -@@ -65,24 +71,37 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) - struct nvkm_alarm *list; - unsigned long flags; - -- alarm->timestamp = nvkm_timer_read(tmr) + nsec; -- -- /* append new alarm to list, in soonest-alarm-first order */ -+ /* Remove alarm from pending list. -+ * -+ * This both protects against the corruption of the list, -+ * and implements alarm rescheduling/cancellation. -+ */ - spin_lock_irqsave(&tmr->lock, flags); -- if (!nsec) { -- if (!list_empty(&alarm->head)) -- list_del(&alarm->head); -- } else { -+ list_del_init(&alarm->head); -+ -+ if (nsec) { -+ /* Insert into pending list, ordered earliest to latest. */ -+ alarm->timestamp = nvkm_timer_read(tmr) + nsec; - list_for_each_entry(list, &tmr->alarms, head) { - if (list->timestamp > alarm->timestamp) - break; - } -+ - list_add_tail(&alarm->head, &list->head); -+ -+ /* Update HW if this is now the earliest alarm. */ -+ list = list_first_entry(&tmr->alarms, typeof(*list), head); -+ if (list == alarm) { -+ tmr->func->alarm_init(tmr, alarm->timestamp); -+ /* This shouldn't happen if callers aren't stupid. -+ * -+ * Worst case scenario is that it'll take roughly -+ * 4 seconds for the next alarm to trigger. -+ */ -+ WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr)); -+ } - } - spin_unlock_irqrestore(&tmr->lock, flags); -- -- /* process pending alarms */ -- nvkm_timer_alarm_trigger(tmr); - } - - void -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c -index 7b9ce87f0617..7f48249f41de 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c -@@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr) - u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0); - - if (stat & 0x00000001) { -- nvkm_timer_alarm_trigger(tmr); - nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001); -+ nvkm_timer_alarm_trigger(tmr); - stat &= ~0x00000001; - } - -diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c -index e690dd11e99f..4b0f942b8914 100644 ---- a/drivers/iio/dac/ad7303.c -+++ b/drivers/iio/dac/ad7303.c -@@ -184,9 +184,9 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { - .address = (chan), \ - .scan_type = { \ - .sign = 'u', \ -- .realbits = '8', \ -- .storagebits = '8', \ -- .shift = '0', \ -+ .realbits = 8, \ -+ .storagebits = 8, \ -+ .shift = 0, \ - }, \ - .ext_info = ad7303_ext_info, \ - } -diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c -index a0aedda7dfd7..bf0bd7e03aff 100644 ---- a/drivers/iio/proximity/as3935.c -+++ b/drivers/iio/proximity/as3935.c -@@ -50,7 +50,6 @@ - #define AS3935_TUNE_CAP 0x08 - #define AS3935_CALIBRATE 0x3D - --#define AS3935_WRITE_DATA BIT(15) - #define AS3935_READ_DATA BIT(14) - #define AS3935_ADDRESS(x) ((x) << 8) - -@@ -105,7 +104,7 @@ static int as3935_write(struct as3935_state *st, - { - u8 *buf = st->buf; - -- buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8; -+ buf[0] = AS3935_ADDRESS(reg) >> 8; - buf[1] = val; - - return spi_write(st->spi, buf, 2); -diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c -index 34b1adad07aa..6a8024d9d742 100644 ---- a/drivers/infiniband/core/addr.c -+++ b/drivers/infiniband/core/addr.c -@@ -277,8 +277,8 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, - fl6.saddr = src_in->sin6_addr; - fl6.flowi6_oif = addr->bound_dev_if; - -- dst = ip6_route_output(addr->net, NULL, &fl6); -- if ((ret = dst->error)) -+ ret = ipv6_stub->ipv6_dst_lookup(addr->net, NULL, &dst, &fl6); -+ if (ret < 0) - goto put; - - if (ipv6_addr_any(&fl6.saddr)) { -diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c -index 0628372f3591..b92b8a724efb 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c -@@ -2005,11 +2005,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain, - if (context_copied(context)) { - u16 did_old = context_domain_id(context); - -- if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) -+ if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) { - iommu->flush.flush_context(iommu, did_old, - (((u16)bus) << 8) | devfn, - DMA_CCMD_MASK_NOBIT, - DMA_CCMD_DEVICE_INVL); -+ iommu->flush.flush_iotlb(iommu, did_old, 0, 0, -+ DMA_TLB_DSI_FLUSH); -+ } - } - - pgd = domain->pgd; -diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig -index 7913fdcfc849..108249f52fa9 100644 ---- a/drivers/md/Kconfig -+++ b/drivers/md/Kconfig -@@ -357,6 +357,7 @@ config DM_LOG_USERSPACE - config DM_RAID - tristate "RAID 1/4/5/6/10 target" - depends on BLK_DEV_DM -+ select MD_RAID0 - select MD_RAID1 - select MD_RAID10 - select MD_RAID456 -diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c -index 2dd33085b331..cdceefd0e57d 100644 ---- a/drivers/md/dm-bufio.c -+++ b/drivers/md/dm-bufio.c -@@ -222,7 +222,7 @@ static DEFINE_SPINLOCK(param_spinlock); - * Buffers are freed after this timeout - */ - static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS; --static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; -+static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES; - - static unsigned long dm_bufio_peak_allocated; - static unsigned long dm_bufio_allocated_kmem_cache; -@@ -914,10 +914,11 @@ static void __get_memory_limit(struct dm_bufio_client *c, - { - unsigned long buffers; - -- if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) { -- mutex_lock(&dm_bufio_clients_lock); -- __cache_size_refresh(); -- mutex_unlock(&dm_bufio_clients_lock); -+ if (unlikely(ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch)) { -+ if (mutex_trylock(&dm_bufio_clients_lock)) { -+ __cache_size_refresh(); -+ mutex_unlock(&dm_bufio_clients_lock); -+ } - } - - buffers = dm_bufio_cache_size_per_client >> -@@ -1513,10 +1514,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp) - return true; - } - --static unsigned get_retain_buffers(struct dm_bufio_client *c) -+static unsigned long get_retain_buffers(struct dm_bufio_client *c) - { -- unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); -- return retain_bytes / c->block_size; -+ unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes); -+ return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT); - } - - static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, -@@ -1526,7 +1527,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, - struct dm_buffer *b, *tmp; - unsigned long freed = 0; - unsigned long count = nr_to_scan; -- unsigned retain_target = get_retain_buffers(c); -+ unsigned long retain_target = get_retain_buffers(c); - - for (l = 0; l < LIST_SIZE; l++) { - list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { -@@ -1752,11 +1753,19 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz) - static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz) - { - struct dm_buffer *b, *tmp; -- unsigned retain_target = get_retain_buffers(c); -- unsigned count; -+ unsigned long retain_target = get_retain_buffers(c); -+ unsigned long count; -+ LIST_HEAD(write_list); - - dm_bufio_lock(c); - -+ __check_watermark(c, &write_list); -+ if (unlikely(!list_empty(&write_list))) { -+ dm_bufio_unlock(c); -+ __flush_write_list(&write_list); -+ dm_bufio_lock(c); -+ } -+ - count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY]; - list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_CLEAN], lru_list) { - if (count <= retain_target) -@@ -1781,6 +1790,8 @@ static void cleanup_old_buffers(void) - - mutex_lock(&dm_bufio_clients_lock); - -+ __cache_size_refresh(); -+ - list_for_each_entry(c, &dm_bufio_all_clients, client_list) - __evict_old_buffers(c, max_age_hz); - -@@ -1904,7 +1915,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache"); - module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds"); - --module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR); -+module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory"); - - module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR); -diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c -index 3970cda10080..d3c55d7754af 100644 ---- a/drivers/md/dm-cache-metadata.c -+++ b/drivers/md/dm-cache-metadata.c -@@ -1326,17 +1326,19 @@ void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, - - int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown) - { -- int r; -+ int r = -EINVAL; - flags_mutator mutator = (clean_shutdown ? set_clean_shutdown : - clear_clean_shutdown); - - WRITE_LOCK(cmd); -+ if (cmd->fail_io) -+ goto out; -+ - r = __commit_transaction(cmd, mutator); - if (r) - goto out; - - r = __begin_transaction(cmd); -- - out: - WRITE_UNLOCK(cmd); - return r; -@@ -1348,7 +1350,8 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd, - int r = -EINVAL; - - READ_LOCK(cmd); -- r = dm_sm_get_nr_free(cmd->metadata_sm, result); -+ if (!cmd->fail_io) -+ r = dm_sm_get_nr_free(cmd->metadata_sm, result); - READ_UNLOCK(cmd); - - return r; -@@ -1360,7 +1363,8 @@ int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd, - int r = -EINVAL; - - READ_LOCK(cmd); -- r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); -+ if (!cmd->fail_io) -+ r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); - READ_UNLOCK(cmd); - - return r; -diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c -index 911ada643364..3b67afda430b 100644 ---- a/drivers/md/dm-thin-metadata.c -+++ b/drivers/md/dm-thin-metadata.c -@@ -485,11 +485,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd) - if (r < 0) - return r; - -- r = save_sm_roots(pmd); -+ r = dm_tm_pre_commit(pmd->tm); - if (r < 0) - return r; - -- r = dm_tm_pre_commit(pmd->tm); -+ r = save_sm_roots(pmd); - if (r < 0) - return r; - -diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c -index b1ced58eb5e1..a1a68209bd36 100644 ---- a/drivers/md/persistent-data/dm-btree.c -+++ b/drivers/md/persistent-data/dm-btree.c -@@ -887,8 +887,12 @@ static int find_key(struct ro_spine *s, dm_block_t block, bool find_highest, - else - *result_key = le64_to_cpu(ro_node(s)->keys[0]); - -- if (next_block || flags & INTERNAL_NODE) -- block = value64(ro_node(s), i); -+ if (next_block || flags & INTERNAL_NODE) { -+ if (find_highest) -+ block = value64(ro_node(s), i); -+ else -+ block = value64(ro_node(s), 0); -+ } - - } while (flags & INTERNAL_NODE); - -diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c -index ebb280a14325..32adf6b4a9c7 100644 ---- a/drivers/md/persistent-data/dm-space-map-disk.c -+++ b/drivers/md/persistent-data/dm-space-map-disk.c -@@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b) - - static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b) - { -+ int r; -+ uint32_t old_count; - enum allocation_event ev; - struct sm_disk *smd = container_of(sm, struct sm_disk, sm); - -- return sm_ll_dec(&smd->ll, b, &ev); -+ r = sm_ll_dec(&smd->ll, b, &ev); -+ if (!r && (ev == SM_FREE)) { -+ /* -+ * It's only free if it's also free in the last -+ * transaction. -+ */ -+ r = sm_ll_lookup(&smd->old_ll, b, &old_count); -+ if (!r && !old_count) -+ smd->nr_allocated_this_transaction--; -+ } -+ -+ return r; - } - - static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 7af976934441..4384b46cee1a 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -2232,6 +2232,10 @@ static int resize_stripes(struct r5conf *conf, int newsize) - err = -ENOMEM; - - mutex_unlock(&conf->cache_size_mutex); -+ -+ conf->slab_cache = sc; -+ conf->active_name = 1-conf->active_name; -+ - /* Step 4, return new stripes to service */ - while(!list_empty(&newstripes)) { - nsh = list_entry(newstripes.next, struct stripe_head, lru); -@@ -2249,8 +2253,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) - } - /* critical section pass, GFP_NOIO no longer needed */ - -- conf->slab_cache = sc; -- conf->active_name = 1-conf->active_name; - if (!err) - conf->pool_size = newsize; - return err; -diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c -index fdffb2f0ded8..107853b0fddd 100644 ---- a/drivers/media/dvb-frontends/cxd2841er.c -+++ b/drivers/media/dvb-frontends/cxd2841er.c -@@ -2678,7 +2678,9 @@ static struct dvb_frontend_ops cxd2841er_dvbt_t2_ops = { - FE_CAN_MUTE_TS | - FE_CAN_2G_MODULATION, - .frequency_min = 42000000, -- .frequency_max = 1002000000 -+ .frequency_max = 1002000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000 - }, - .init = cxd2841er_init_tc, - .sleep = cxd2841er_sleep_tc, -diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c -index c8946f98ced4..7727789dbda1 100644 ---- a/drivers/media/platform/s5p-mfc/s5p_mfc.c -+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c -@@ -173,6 +173,7 @@ static void s5p_mfc_watchdog_worker(struct work_struct *work) - } - s5p_mfc_clock_on(); - ret = s5p_mfc_init_hw(dev); -+ s5p_mfc_clock_off(); - if (ret) - mfc_err("Failed to reinit FW\n"); - } -diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c -index 2cdb740cde48..f838d9c7ed12 100644 ---- a/drivers/media/rc/mceusb.c -+++ b/drivers/media/rc/mceusb.c -@@ -1321,8 +1321,8 @@ static int mceusb_dev_probe(struct usb_interface *intf, - } - } - } -- if (ep_in == NULL) { -- dev_dbg(&intf->dev, "inbound and/or endpoint not found"); -+ if (!ep_in || !ep_out) { -+ dev_dbg(&intf->dev, "required endpoints not found\n"); - return -ENODEV; - } - -diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c -index 317ef63ee789..8d96a22647b3 100644 ---- a/drivers/media/tuners/tuner-xc2028.c -+++ b/drivers/media/tuners/tuner-xc2028.c -@@ -281,6 +281,14 @@ static void free_firmware(struct xc2028_data *priv) - int i; - tuner_dbg("%s called\n", __func__); - -+ /* free allocated f/w string */ -+ if (priv->fname != firmware_name) -+ kfree(priv->fname); -+ priv->fname = NULL; -+ -+ priv->state = XC2028_NO_FIRMWARE; -+ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); -+ - if (!priv->firm) - return; - -@@ -291,9 +299,6 @@ static void free_firmware(struct xc2028_data *priv) - - priv->firm = NULL; - priv->firm_size = 0; -- priv->state = XC2028_NO_FIRMWARE; -- -- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); - } - - static int load_all_firmwares(struct dvb_frontend *fe, -@@ -884,9 +889,8 @@ read_not_reliable: - return 0; - - fail: -- priv->state = XC2028_NO_FIRMWARE; -+ free_firmware(priv); - -- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); - if (retry_count < 8) { - msleep(50); - retry_count++; -@@ -1332,11 +1336,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) - mutex_lock(&xc2028_list_mutex); - - /* only perform final cleanup if this is the last instance */ -- if (hybrid_tuner_report_instance_count(priv) == 1) { -+ if (hybrid_tuner_report_instance_count(priv) == 1) - free_firmware(priv); -- kfree(priv->ctrl.fname); -- priv->ctrl.fname = NULL; -- } - - if (priv) - hybrid_tuner_release_state(priv); -@@ -1399,19 +1400,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) - - /* - * Copy the config data. -- * For the firmware name, keep a local copy of the string, -- * in order to avoid troubles during device release. - */ -- kfree(priv->ctrl.fname); -- priv->ctrl.fname = NULL; - memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); -- if (p->fname) { -- priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); -- if (priv->ctrl.fname == NULL) { -- rc = -ENOMEM; -- goto unlock; -- } -- } - - /* - * If firmware name changed, frees firmware. As free_firmware will -@@ -1426,10 +1416,15 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) - - if (priv->state == XC2028_NO_FIRMWARE) { - if (!firmware_name[0]) -- priv->fname = priv->ctrl.fname; -+ priv->fname = kstrdup(p->fname, GFP_KERNEL); - else - priv->fname = firmware_name; - -+ if (!priv->fname) { -+ rc = -ENOMEM; -+ goto unlock; -+ } -+ - rc = request_firmware_nowait(THIS_MODULE, 1, - priv->fname, - priv->i2c_props.adap->dev.parent, -diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c -index de4ae5eb4830..10d8a08e36e6 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-audio.c -+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c -@@ -671,10 +671,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) - - spin_lock_init(&adev->slock); - err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); -- if (err < 0) { -- snd_card_free(card); -- return err; -- } -+ if (err < 0) -+ goto err_free_card; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_cx231xx_pcm_capture); -@@ -688,10 +686,9 @@ static int cx231xx_audio_init(struct cx231xx *dev) - INIT_WORK(&dev->wq_trigger, audio_trigger); - - err = snd_card_register(card); -- if (err < 0) { -- snd_card_free(card); -- return err; -- } -+ if (err < 0) -+ goto err_free_card; -+ - adev->sndcard = card; - adev->udev = dev->udev; - -@@ -701,6 +698,11 @@ static int cx231xx_audio_init(struct cx231xx *dev) - hs_config_info[0].interface_info. - audio_index + 1]; - -+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { -+ err = -ENODEV; -+ goto err_free_card; -+ } -+ - adev->end_point_addr = - uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress; -@@ -710,13 +712,20 @@ static int cx231xx_audio_init(struct cx231xx *dev) - "audio EndPoint Addr 0x%x, Alternate settings: %i\n", - adev->end_point_addr, adev->num_alt); - adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); -- -- if (adev->alt_max_pkt_size == NULL) -- return -ENOMEM; -+ if (!adev->alt_max_pkt_size) { -+ err = -ENOMEM; -+ goto err_free_card; -+ } - - for (i = 0; i < adev->num_alt; i++) { -- u16 tmp = -- le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { -+ err = -ENODEV; -+ goto err_free_pkt_size; -+ } -+ -+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. - wMaxPacketSize); - adev->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); -@@ -726,6 +735,13 @@ static int cx231xx_audio_init(struct cx231xx *dev) - } - - return 0; -+ -+err_free_pkt_size: -+ kfree(adev->alt_max_pkt_size); -+err_free_card: -+ snd_card_free(card); -+ -+ return err; - } - - static int cx231xx_audio_fini(struct cx231xx *dev) -diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c -index 8389c162bc89..2c5f76d588ac 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-cards.c -+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c -@@ -1447,6 +1447,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - - uif = udev->actconfig->interface[idx]; - -+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ - dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress; - dev->video_mode.num_alt = uif->num_altsetting; - -@@ -1460,7 +1463,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - return -ENOMEM; - - for (i = 0; i < dev->video_mode.num_alt; i++) { -- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ -+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); - dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); - dev_dbg(dev->dev, - "Alternate setting %i, max size= %i\n", i, -@@ -1477,6 +1485,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - } - uif = udev->actconfig->interface[idx]; - -+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ - dev->vbi_mode.end_point_addr = - uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress; -@@ -1493,8 +1504,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - return -ENOMEM; - - for (i = 0; i < dev->vbi_mode.num_alt; i++) { -- u16 tmp = -- le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ -+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->vbi_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); -@@ -1514,6 +1529,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - } - uif = udev->actconfig->interface[idx]; - -+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ - dev->sliced_cc_mode.end_point_addr = - uif->altsetting[0].endpoint[isoc_pipe].desc. - bEndpointAddress; -@@ -1528,7 +1546,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, - return -ENOMEM; - - for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { -- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) -+ return -ENODEV; -+ -+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. - desc.wMaxPacketSize); - dev->sliced_cc_mode.alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); -@@ -1693,6 +1716,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface, - } - uif = udev->actconfig->interface[idx]; - -+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { -+ retval = -ENODEV; -+ goto err_video_alt; -+ } -+ - dev->ts1_mode.end_point_addr = - uif->altsetting[0].endpoint[isoc_pipe]. - desc.bEndpointAddress; -@@ -1710,7 +1738,14 @@ static int cx231xx_usb_probe(struct usb_interface *interface, - } - - for (i = 0; i < dev->ts1_mode.num_alt; i++) { -- u16 tmp = le16_to_cpu(uif->altsetting[i]. -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { -+ retval = -ENODEV; -+ goto err_video_alt; -+ } -+ -+ tmp = le16_to_cpu(uif->altsetting[i]. - endpoint[isoc_pipe].desc. - wMaxPacketSize); - dev->ts1_mode.alt_max_pkt_size[i] = -diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c -index ab58f0b9da5c..d1b4b729e814 100644 ---- a/drivers/media/usb/dvb-usb/dib0700_core.c -+++ b/drivers/media/usb/dvb-usb/dib0700_core.c -@@ -783,6 +783,9 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) - - /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ - -+ if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) -+ return -ENODEV; -+ - purb = usb_alloc_urb(0, GFP_KERNEL); - if (purb == NULL) { - err("rc usb alloc urb failed"); -diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c -index f10717311e05..dd93c2c8fea9 100644 ---- a/drivers/media/usb/dvb-usb/ttusb2.c -+++ b/drivers/media/usb/dvb-usb/ttusb2.c -@@ -78,6 +78,9 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, - u8 *s, *r = NULL; - int ret = 0; - -+ if (4 + rlen > 64) -+ return -EIO; -+ - s = kzalloc(wlen+4, GFP_KERNEL); - if (!s) - return -ENOMEM; -@@ -381,6 +384,22 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num - write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD); - read = msg[i].flags & I2C_M_RD; - -+ if (3 + msg[i].len > sizeof(obuf)) { -+ err("i2c wr len=%d too high", msg[i].len); -+ break; -+ } -+ if (write_read) { -+ if (3 + msg[i+1].len > sizeof(ibuf)) { -+ err("i2c rd len=%d too high", msg[i+1].len); -+ break; -+ } -+ } else if (read) { -+ if (3 + msg[i].len > sizeof(ibuf)) { -+ err("i2c rd len=%d too high", msg[i].len); -+ break; -+ } -+ } -+ - obuf[0] = (msg[i].addr << 1) | (write_read | read); - if (read) - obuf[1] = 0; -diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c -index 0712b1bc90b4..0f6d57fbf91b 100644 ---- a/drivers/media/usb/gspca/konica.c -+++ b/drivers/media/usb/gspca/konica.c -@@ -188,6 +188,9 @@ static int sd_start(struct gspca_dev *gspca_dev) - return -EIO; - } - -+ if (alt->desc.bNumEndpoints < 2) -+ return -ENODEV; -+ - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); - - n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; -diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c -index d1dc1a198e3e..91d709efef7a 100644 ---- a/drivers/media/usb/usbvision/usbvision-video.c -+++ b/drivers/media/usb/usbvision/usbvision-video.c -@@ -1523,7 +1523,14 @@ static int usbvision_probe(struct usb_interface *intf, - } - - for (i = 0; i < usbvision->num_alt; i++) { -- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. -+ u16 tmp; -+ -+ if (uif->altsetting[i].desc.bNumEndpoints < 2) { -+ ret = -ENODEV; -+ goto err_pkt; -+ } -+ -+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. - wMaxPacketSize); - usbvision->alt_max_pkt_size[i] = - (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); -diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c -index 7433ba5c4bad..fd6a3b36208e 100644 ---- a/drivers/media/usb/zr364xx/zr364xx.c -+++ b/drivers/media/usb/zr364xx/zr364xx.c -@@ -604,6 +604,14 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, - ptr = pdest = frm->lpvbits; - - if (frm->ulState == ZR364XX_READ_IDLE) { -+ if (purb->actual_length < 128) { -+ /* header incomplete */ -+ dev_info(&cam->udev->dev, -+ "%s: buffer (%d bytes) too small to hold jpeg header. Discarding.\n", -+ __func__, purb->actual_length); -+ return -EINVAL; -+ } -+ - frm->ulState = ZR364XX_READ_FRAME; - frm->cur_size = 0; - -diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c -index 25f21968fa5c..de2ea9f2f966 100644 ---- a/drivers/net/irda/irda-usb.c -+++ b/drivers/net/irda/irda-usb.c -@@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) - * are "42101001.sb" or "42101002.sb" - */ - sprintf(stir421x_fw_name, "4210%4X.sb", -- self->usbdev->descriptor.bcdDevice); -+ le16_to_cpu(self->usbdev->descriptor.bcdDevice)); - ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); - if (ret < 0) - return ret; -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index 09052f9e324f..c6f5d9a6bec6 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -754,6 +754,7 @@ static const struct usb_device_id products[] = { - {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ - {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ - {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ -+ {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */ - - /* 4. Gobi 1000 devices */ - {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c -index 165dd202c365..c92564b3ec85 100644 ---- a/drivers/net/wireless/ath/ath9k/hif_usb.c -+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c -@@ -37,6 +37,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { - { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ - { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ - { USB_DEVICE(0x0471, 0x209e) }, /* Philips (or NXP) PTA01 */ -+ { USB_DEVICE(0x1eda, 0x2315) }, /* AirTies */ - - { USB_DEVICE(0x0cf3, 0x7015), - .driver_info = AR9287_USB }, /* Atheros */ -@@ -1216,6 +1217,9 @@ static int send_eject_command(struct usb_interface *interface) - u8 bulk_out_ep; - int r; - -+ if (iface_desc->desc.bNumEndpoints < 2) -+ return -ENODEV; -+ - /* Find bulk out endpoint */ - for (r = 1; r >= 0; r--) { - endpoint = &iface_desc->endpoint[r].desc; -diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c -index 21192b6f9c64..268e50ba88a5 100644 ---- a/drivers/net/wireless/mwifiex/pcie.c -+++ b/drivers/net/wireless/mwifiex/pcie.c -@@ -947,6 +947,7 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) - if (card && card->cmd_buf) { - mwifiex_unmap_pci_memory(adapter, card->cmd_buf, - PCI_DMA_TODEVICE); -+ dev_kfree_skb_any(card->cmd_buf); - } - return 0; - } -@@ -1513,6 +1514,11 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) - return -1; - - card->cmd_buf = skb; -+ /* -+ * Need to keep a reference, since core driver might free up this -+ * buffer before we've unmapped it. -+ */ -+ skb_get(skb); - - /* To send a command, the driver will: - 1. Write the 64bit physical address of the data buffer to -@@ -1610,6 +1616,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) - if (card->cmd_buf) { - mwifiex_unmap_pci_memory(adapter, card->cmd_buf, - PCI_DMA_TODEVICE); -+ dev_kfree_skb_any(card->cmd_buf); - card->cmd_buf = NULL; - } - -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c -index 9b4d8a637915..4b354918e183 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c -@@ -359,6 +359,107 @@ bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw) - return rtl8821ae_phy_rf6052_config(hw); - } - -+static void _rtl8812ae_phy_set_rfe_reg_24g(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u8 tmp; -+ -+ switch (rtlhal->rfe_type) { -+ case 3: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337770); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337770); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); -+ break; -+ case 4: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x001); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x001); -+ break; -+ case 5: -+ rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x77); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); -+ tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); -+ rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp & ~0x1); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); -+ break; -+ case 1: -+ if (rtlpriv->btcoexist.bt_coexistence) { -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x777777); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, -+ 0x77777777); -+ rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); -+ break; -+ } -+ case 0: -+ case 2: -+ default: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77777777); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77777777); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); -+ break; -+ } -+} -+ -+static void _rtl8812ae_phy_set_rfe_reg_5g(struct ieee80211_hw *hw) -+{ -+ struct rtl_priv *rtlpriv = rtl_priv(hw); -+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -+ u8 tmp; -+ -+ switch (rtlhal->rfe_type) { -+ case 0: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337717); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337717); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); -+ break; -+ case 1: -+ if (rtlpriv->btcoexist.bt_coexistence) { -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xffffff, 0x337717); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, -+ 0x77337717); -+ rtl_set_bbreg(hw, RA_RFE_INV, 0x33f00000, 0x000); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); -+ } else { -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, -+ 0x77337717); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, -+ 0x77337717); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x000); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x000); -+ } -+ break; -+ case 3: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x54337717); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x54337717); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, 0x900, 0x00000303, 0x1); -+ break; -+ case 5: -+ rtl_write_byte(rtlpriv, RA_RFE_PINMUX + 2, 0x33); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); -+ tmp = rtl_read_byte(rtlpriv, RA_RFE_INV + 3); -+ rtl_write_byte(rtlpriv, RA_RFE_INV + 3, tmp | 0x1); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); -+ break; -+ case 2: -+ case 4: -+ default: -+ rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, 0x77337777); -+ rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, 0x77337777); -+ rtl_set_bbreg(hw, RA_RFE_INV, BMASKRFEINV, 0x010); -+ rtl_set_bbreg(hw, RB_RFE_INV, BMASKRFEINV, 0x010); -+ break; -+ } -+} -+ - u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, - u8 rf_path) - { -@@ -553,14 +654,9 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) - /* 0x82C[1:0] = 2b'00 */ - rtl_set_bbreg(hw, 0x82c, 0x3, 0); - } -- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { -- rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, -- 0x77777777); -- rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, -- 0x77777777); -- rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000); -- rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000); -- } -+ -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) -+ _rtl8812ae_phy_set_rfe_reg_24g(hw); - - rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1); - rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1); -@@ -615,14 +711,8 @@ void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) - /* 0x82C[1:0] = 2'b00 */ - rtl_set_bbreg(hw, 0x82c, 0x3, 1); - -- if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { -- rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, -- 0x77337777); -- rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, -- 0x77337777); -- rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010); -- rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010); -- } -+ if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) -+ _rtl8812ae_phy_set_rfe_reg_5g(hw); - - rtl_set_bbreg(hw, RTXPATH, 0xf0, 0); - rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf); -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h -index 1d6110f9c1fb..ed69dbe178ff 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h -@@ -2424,6 +2424,7 @@ - #define BMASKH4BITS 0xf0000000 - #define BMASKOFDM_D 0xffc00000 - #define BMASKCCK 0x3f3f3f3f -+#define BMASKRFEINV 0x3ff00000 - - #define BRFREGOFFSETMASK 0xfffff - -diff --git a/drivers/of/address.c b/drivers/of/address.c -index 9582c5703b3c..4fe5fe21cd49 100644 ---- a/drivers/of/address.c -+++ b/drivers/of/address.c -@@ -260,7 +260,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, - if (!parser->range || parser->range + parser->np > parser->end) - return NULL; - -- range->pci_space = parser->range[0]; -+ range->pci_space = be32_to_cpup(parser->range); - range->flags = of_bus_pci_get_flags(parser->range); - range->pci_addr = of_read_number(parser->range + 1, ns); - range->cpu_addr = of_translate_address(parser->node, -diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index d7508704c992..f8b2b5987ea9 100644 ---- a/drivers/pci/pci-sysfs.c -+++ b/drivers/pci/pci-sysfs.c -@@ -973,15 +973,19 @@ void pci_remove_legacy_files(struct pci_bus *b) - int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, - enum pci_mmap_api mmap_api) - { -- unsigned long nr, start, size, pci_start; -+ unsigned long nr, start, size; -+ resource_size_t pci_start = 0, pci_end; - - if (pci_resource_len(pdev, resno) == 0) - return 0; - nr = vma_pages(vma); - start = vma->vm_pgoff; - size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; -- pci_start = (mmap_api == PCI_MMAP_PROCFS) ? -- pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; -+ if (mmap_api == PCI_MMAP_PROCFS) { -+ pci_resource_to_user(pdev, resno, &pdev->resource[resno], -+ &pci_start, &pci_end); -+ pci_start >>= PAGE_SHIFT; -+ } - if (start >= pci_start && start < pci_start + size && - start + nr <= pci_start + size) - return 1; -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index 0e53488f8ec1..1a14ca8965e6 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -1732,8 +1732,8 @@ static void pci_pme_list_scan(struct work_struct *work) - } - } - if (!list_empty(&pci_pme_list)) -- schedule_delayed_work(&pci_pme_work, -- msecs_to_jiffies(PME_TIMEOUT)); -+ queue_delayed_work(system_freezable_wq, &pci_pme_work, -+ msecs_to_jiffies(PME_TIMEOUT)); - mutex_unlock(&pci_pme_list_mutex); - } - -@@ -1798,8 +1798,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable) - mutex_lock(&pci_pme_list_mutex); - list_add(&pme_dev->list, &pci_pme_list); - if (list_is_singular(&pci_pme_list)) -- schedule_delayed_work(&pci_pme_work, -- msecs_to_jiffies(PME_TIMEOUT)); -+ queue_delayed_work(system_freezable_wq, -+ &pci_pme_work, -+ msecs_to_jiffies(PME_TIMEOUT)); - mutex_unlock(&pci_pme_list_mutex); - } else { - mutex_lock(&pci_pme_list_mutex); -diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c -index d2c3d7cc35f5..5ca6d2130593 100644 ---- a/drivers/regulator/tps65023-regulator.c -+++ b/drivers/regulator/tps65023-regulator.c -@@ -311,8 +311,7 @@ static int tps_65023_probe(struct i2c_client *client, - - /* Enable setting output voltage by I2C */ - regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, -- TPS65023_REG_CTRL2_CORE_ADJ, -- TPS65023_REG_CTRL2_CORE_ADJ); -+ TPS65023_REG_CTRL2_CORE_ADJ, 0); - - return 0; - } -diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -index e9c4f973bba9..79bf13f5c0d1 100644 ---- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) - - switch (variable) { - case HW_VAR_BSSID: -- rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]); -- rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]); -+ /* BSSIDR 2 byte alignment */ -+ rtl92e_writew(dev, BSSIDR, *(u16 *)val); -+ rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2)); - break; - - case HW_VAR_MEDIA_STATUS: -@@ -626,7 +627,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev) - struct r8192_priv *priv = rtllib_priv(dev); - - RT_TRACE(COMP_INIT, "===========>%s()\n", __func__); -- curCR = rtl92e_readl(dev, EPROM_CMD); -+ curCR = rtl92e_readw(dev, EPROM_CMD); - RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, - curCR); - priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : -@@ -963,8 +964,8 @@ static void _rtl92e_net_update(struct net_device *dev) - rtl92e_config_rate(dev, &rate_config); - priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; - priv->basic_rate = rate_config &= 0x15f; -- rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]); -- rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]); -+ rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid); -+ rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2)); - - if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { - rtl92e_writew(dev, ATIMWND, 2); -diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c -index 96849e2e7435..0b7194086c5a 100644 ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -311,6 +311,12 @@ static void acm_ctrl_irq(struct urb *urb) - break; - - case USB_CDC_NOTIFY_SERIAL_STATE: -+ if (le16_to_cpu(dr->wLength) != 2) { -+ dev_dbg(&acm->control->dev, -+ "%s - malformed serial state\n", __func__); -+ break; -+ } -+ - newctrl = get_unaligned_le16(data); - - if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { -@@ -347,11 +353,10 @@ static void acm_ctrl_irq(struct urb *urb) - - default: - dev_dbg(&acm->control->dev, -- "%s - unknown notification %d received: index %d " -- "len %d data0 %d data1 %d\n", -+ "%s - unknown notification %d received: index %d len %d\n", - __func__, -- dr->bNotificationType, dr->wIndex, -- dr->wLength, data[0], data[1]); -+ dr->bNotificationType, dr->wIndex, dr->wLength); -+ - break; - } - exit: -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index f5c92d904ded..54d2d6b604c0 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -373,11 +373,11 @@ static void snoop_urb(struct usb_device *udev, - - if (userurb) { /* Async */ - if (when == SUBMIT) -- dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " -+ dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " - "length %u\n", - userurb, ep, t, d, length); - else -- dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " -+ dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " - "actual_length %u status %d\n", - userurb, ep, t, d, length, - timeout_or_status); -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index ca2cbdb3aa67..c3f4f2ab7b33 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -1696,7 +1696,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) - if (retval == 0) - retval = -EINPROGRESS; - else if (retval != -EIDRM && retval != -EBUSY) -- dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", -+ dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", - urb, retval); - usb_put_dev(udev); - } -@@ -1863,7 +1863,7 @@ rescan: - /* kick hcd */ - unlink1(hcd, urb, -ESHUTDOWN); - dev_dbg (hcd->self.controller, -- "shutdown urb %p ep%d%s%s\n", -+ "shutdown urb %pK ep%d%s%s\n", - urb, usb_endpoint_num(&ep->desc), - is_in ? "in" : "out", - ({ char *s; -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 67961231cbbd..b627392ad52a 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -358,7 +358,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev) - } - - /* USB 2.0 spec Section 11.24.4.5 */ --static int get_hub_descriptor(struct usb_device *hdev, void *data) -+static int get_hub_descriptor(struct usb_device *hdev, -+ struct usb_hub_descriptor *desc) - { - int i, ret, size; - unsigned dtype; -@@ -374,10 +375,18 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data) - for (i = 0; i < 3; i++) { - ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, -- dtype << 8, 0, data, size, -+ dtype << 8, 0, desc, size, - USB_CTRL_GET_TIMEOUT); -- if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) -+ if (hub_is_superspeed(hdev)) { -+ if (ret == size) -+ return ret; -+ } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) { -+ /* Make sure we have the DeviceRemovable field. */ -+ size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1; -+ if (ret < size) -+ return -EMSGSIZE; - return ret; -+ } - } - return -EINVAL; - } -@@ -1295,7 +1304,7 @@ static int hub_configure(struct usb_hub *hub, - } - mutex_init(&hub->status_mutex); - -- hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); -+ hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL); - if (!hub->descriptor) { - ret = -ENOMEM; - goto fail; -@@ -1303,7 +1312,7 @@ static int hub_configure(struct usb_hub *hub, - - /* Request the entire hub descriptor. - * hub->descriptor can handle USB_MAXCHILDREN ports, -- * but the hub can/will return fewer bytes here. -+ * but a (non-SS) hub can/will return fewer bytes here. - */ - ret = get_hub_descriptor(hdev, hub->descriptor); - if (ret < 0) { -diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c -index c601e25b609f..e43ef7d2d00e 100644 ---- a/drivers/usb/core/urb.c -+++ b/drivers/usb/core/urb.c -@@ -335,7 +335,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) - if (!urb || !urb->complete) - return -EINVAL; - if (urb->hcpriv) { -- WARN_ONCE(1, "URB %p submitted while active\n", urb); -+ WARN_ONCE(1, "URB %pK submitted while active\n", urb); - return -EBUSY; - } - -diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c -index 5d70d46239bb..cf6bbaff42d0 100644 ---- a/drivers/usb/host/xhci-mem.c -+++ b/drivers/usb/host/xhci-mem.c -@@ -1709,7 +1709,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) - xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); - for (i = 0; i < num_sp; i++) { - dma_addr_t dma; -- void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, -+ void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma, - flags); - if (!buf) - goto fail_sp5; -diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c -index dd262f418140..30c4ae80c8f9 100644 ---- a/drivers/usb/host/xhci-pci.c -+++ b/drivers/usb/host/xhci-pci.c -@@ -52,6 +52,7 @@ - #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 - #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 - #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 -+#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 - - static const char hcd_name[] = "xhci_hcd"; - -@@ -167,12 +168,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) - pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || -- pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) { -+ pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || -+ pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { - xhci->quirks |= XHCI_PME_STUCK_QUIRK; - } - if (pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || -- pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) -+ pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || -+ pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) - xhci->quirks |= XHCI_MISSING_CAS; - - if (pdev->vendor == PCI_VENDOR_ID_ETRON && -diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c -index 268829db9e88..062cf8a84a59 100644 ---- a/drivers/usb/host/xhci-plat.c -+++ b/drivers/usb/host/xhci-plat.c -@@ -92,7 +92,7 @@ static int xhci_plat_probe(struct platform_device *pdev) - - irq = platform_get_irq(pdev, 0); - if (irq < 0) -- return -ENODEV; -+ return irq; - - /* Try to set 64-bit DMA first */ - if (WARN_ON(!pdev->dev.dma_mask)) -diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c -index 775690bed4c0..5e43fd881a9c 100644 ---- a/drivers/usb/misc/iowarrior.c -+++ b/drivers/usb/misc/iowarrior.c -@@ -557,7 +557,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, - info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice); - - /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */ -- info.speed = le16_to_cpu(dev->udev->speed); -+ info.speed = dev->udev->speed; - info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber; - info.report_size = dev->report_size; - -diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c -index 4dd531ac5a7f..0ec9ee573ffa 100644 ---- a/drivers/usb/misc/legousbtower.c -+++ b/drivers/usb/misc/legousbtower.c -@@ -317,9 +317,16 @@ static int tower_open (struct inode *inode, struct file *file) - int subminor; - int retval = 0; - struct usb_interface *interface; -- struct tower_reset_reply reset_reply; -+ struct tower_reset_reply *reset_reply; - int result; - -+ reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL); -+ -+ if (!reset_reply) { -+ retval = -ENOMEM; -+ goto exit; -+ } -+ - nonseekable_open(inode, file); - subminor = iminor(inode); - -@@ -364,8 +371,8 @@ static int tower_open (struct inode *inode, struct file *file) - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, -- &reset_reply, -- sizeof(reset_reply), -+ reset_reply, -+ sizeof(*reset_reply), - 1000); - if (result < 0) { - dev_err(&dev->udev->dev, -@@ -406,6 +413,7 @@ unlock_exit: - mutex_unlock(&dev->lock); - - exit: -+ kfree(reset_reply); - return retval; - } - -@@ -808,7 +816,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device - struct lego_usb_tower *dev = NULL; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor* endpoint; -- struct tower_get_version_reply get_version_reply; -+ struct tower_get_version_reply *get_version_reply = NULL; - int i; - int retval = -ENOMEM; - int result; -@@ -898,6 +906,13 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device - dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; - dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; - -+ get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL); -+ -+ if (!get_version_reply) { -+ retval = -ENOMEM; -+ goto error; -+ } -+ - /* get the firmware version and log it */ - result = usb_control_msg (udev, - usb_rcvctrlpipe(udev, 0), -@@ -905,18 +920,19 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, -- &get_version_reply, -- sizeof(get_version_reply), -+ get_version_reply, -+ sizeof(*get_version_reply), - 1000); - if (result < 0) { - dev_err(idev, "LEGO USB Tower get version control request failed\n"); - retval = result; - goto error; - } -- dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d " -- "build %d\n", get_version_reply.major, -- get_version_reply.minor, -- le16_to_cpu(get_version_reply.build_no)); -+ dev_info(&interface->dev, -+ "LEGO USB Tower firmware version is %d.%d build %d\n", -+ get_version_reply->major, -+ get_version_reply->minor, -+ le16_to_cpu(get_version_reply->build_no)); - - /* we can register the device now, as it is ready */ - usb_set_intfdata (interface, dev); -@@ -937,9 +953,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device - USB_MAJOR, dev->minor); - - exit: -+ kfree(get_version_reply); - return retval; - - error: -+ kfree(get_version_reply); - tower_delete(dev); - return retval; - } -diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c -index 4c82077da475..6020024cb87c 100644 ---- a/drivers/usb/musb/tusb6010_omap.c -+++ b/drivers/usb/musb/tusb6010_omap.c -@@ -220,6 +220,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, - u32 dma_remaining; - int src_burst, dst_burst; - u16 csr; -+ u32 psize; - int ch; - s8 dmareq; - s8 sync_dev; -@@ -391,15 +392,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, - - if (chdat->tx) { - /* Send transfer_packet_sz packets at a time */ -- musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, -- chdat->transfer_packet_sz); -+ psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); -+ psize &= ~0x7ff; -+ psize |= chdat->transfer_packet_sz; -+ musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); - - musb_writel(ep_conf, TUSB_EP_TX_OFFSET, - TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); - } else { - /* Receive transfer_packet_sz packets at a time */ -- musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, -- chdat->transfer_packet_sz << 16); -+ psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); -+ psize &= ~(0x7ff << 16); -+ psize |= (chdat->transfer_packet_sz << 16); -+ musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); - - musb_writel(ep_conf, TUSB_EP_RX_OFFSET, - TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); -diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c -index dbd441c1c2ad..e0385d6c0abb 100644 ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -809,10 +809,10 @@ static const struct usb_device_id id_table_combined[] = { - { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, - { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -- { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), -- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -- { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), -- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -+ { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) }, -+ { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) }, -+ { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) }, -+ { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) }, - { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), -@@ -1508,9 +1508,9 @@ static int set_serial_info(struct tty_struct *tty, - (new_serial.flags & ASYNC_FLAGS)); - priv->custom_divisor = new_serial.custom_divisor; - -+check_and_exit: - write_latency_timer(port); - --check_and_exit: - if ((old_priv.flags & ASYNC_SPD_MASK) != - (priv->flags & ASYNC_SPD_MASK)) { - if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) -diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h -index 71fb9e59db71..4fcf1cecb6d7 100644 ---- a/drivers/usb/serial/ftdi_sio_ids.h -+++ b/drivers/usb/serial/ftdi_sio_ids.h -@@ -882,6 +882,8 @@ - /* Olimex */ - #define OLIMEX_VID 0x15BA - #define OLIMEX_ARM_USB_OCD_PID 0x0003 -+#define OLIMEX_ARM_USB_TINY_PID 0x0004 -+#define OLIMEX_ARM_USB_TINY_H_PID 0x002a - #define OLIMEX_ARM_USB_OCD_H_PID 0x002b - - /* -diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c -index f1a8fdcd8674..e98532feb0cc 100644 ---- a/drivers/usb/serial/io_ti.c -+++ b/drivers/usb/serial/io_ti.c -@@ -2349,8 +2349,11 @@ static void change_port_settings(struct tty_struct *tty, - if (!baud) { - /* pick a default, any default... */ - baud = 9600; -- } else -+ } else { -+ /* Avoid a zero divisor. */ -+ baud = min(baud, 461550); - tty_encode_baud_rate(tty, baud, baud); -+ } - - edge_port->baud_rate = baud; - config->wBaudRate = (__u16)((461550L + baud/2) / baud); -diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c -index 9bf82c262c5b..a6c07c6be25f 100644 ---- a/drivers/usb/serial/mct_u232.c -+++ b/drivers/usb/serial/mct_u232.c -@@ -189,7 +189,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, - return -ENOMEM; - - divisor = mct_u232_calculate_baud_rate(serial, value, &speed); -- put_unaligned_le32(cpu_to_le32(divisor), buf); -+ put_unaligned_le32(divisor, buf); - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - MCT_U232_SET_BAUD_RATE_REQUEST, - MCT_U232_SET_REQUEST_TYPE, -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index af67a0de6b5d..3bf61acfc26b 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -281,6 +281,7 @@ static void option_instat_callback(struct urb *urb); - #define TELIT_PRODUCT_LE922_USBCFG0 0x1042 - #define TELIT_PRODUCT_LE922_USBCFG3 0x1043 - #define TELIT_PRODUCT_LE922_USBCFG5 0x1045 -+#define TELIT_PRODUCT_ME910 0x1100 - #define TELIT_PRODUCT_LE920 0x1200 - #define TELIT_PRODUCT_LE910 0x1201 - #define TELIT_PRODUCT_LE910_USBCFG4 0x1206 -@@ -640,6 +641,11 @@ static const struct option_blacklist_info simcom_sim7100e_blacklist = { - .reserved = BIT(5) | BIT(6), - }; - -+static const struct option_blacklist_info telit_me910_blacklist = { -+ .sendsetup = BIT(0), -+ .reserved = BIT(1) | BIT(3), -+}; -+ - static const struct option_blacklist_info telit_le910_blacklist = { - .sendsetup = BIT(0), - .reserved = BIT(1) | BIT(2), -@@ -1235,6 +1241,8 @@ static const struct usb_device_id option_ids[] = { - .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff), - .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, -+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), -+ .driver_info = (kernel_ulong_t)&telit_me910_blacklist }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), - .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), -diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c -index 38b3f0d8cd58..fd509ed6cf70 100644 ---- a/drivers/usb/serial/qcserial.c -+++ b/drivers/usb/serial/qcserial.c -@@ -162,6 +162,8 @@ static const struct usb_device_id id_table[] = { - {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ - {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ - {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */ -+ {DEVICE_SWI(0x1199, 0x907a)}, /* Sierra Wireless EM74xx QDL */ -+ {DEVICE_SWI(0x1199, 0x907b)}, /* Sierra Wireless EM74xx */ - {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ - {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ - {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ -diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c -index f3cf4cecd2b7..091e8ec7a6c0 100644 ---- a/drivers/usb/storage/ene_ub6250.c -+++ b/drivers/usb/storage/ene_ub6250.c -@@ -446,6 +446,10 @@ struct ms_lib_ctrl { - #define SD_BLOCK_LEN 9 - - struct ene_ub6250_info { -+ -+ /* I/O bounce buffer */ -+ u8 *bbuf; -+ - /* for 6250 code */ - struct SD_STATUS SD_Status; - struct MS_STATUS MS_Status; -@@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag); - - static void ene_ub6250_info_destructor(void *extra) - { -+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra; -+ - if (!extra) - return; -+ kfree(info->bbuf); - } - - static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) -@@ -858,8 +865,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, - u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) - { - struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; -+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -+ u8 *bbuf = info->bbuf; - int result; -- u8 ExtBuf[4]; - u32 bn = PhyBlockAddr * 0x20 + PageNum; - - /* printk(KERN_INFO "MS --- MS_ReaderReadPage, -@@ -902,7 +910,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, - bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); - bcb->CDB[6] = 0x01; - -- result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); -+ result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); - if (result != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - -@@ -911,9 +919,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, - ExtraDat->status0 = 0x10; /* Not yet,fireware support */ - - ExtraDat->status1 = 0x00; /* Not yet,fireware support */ -- ExtraDat->ovrflg = ExtBuf[0]; -- ExtraDat->mngflg = ExtBuf[1]; -- ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); -+ ExtraDat->ovrflg = bbuf[0]; -+ ExtraDat->mngflg = bbuf[1]; -+ ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); - - return USB_STOR_TRANSPORT_GOOD; - } -@@ -1339,8 +1347,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, - u8 PageNum, struct ms_lib_type_extdat *ExtraDat) - { - struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; -+ struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -+ u8 *bbuf = info->bbuf; - int result; -- u8 ExtBuf[4]; - - /* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */ - memset(bcb, 0, sizeof(struct bulk_cb_wrap)); -@@ -1355,7 +1364,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, - bcb->CDB[2] = (unsigned char)(PhyBlock>>16); - bcb->CDB[6] = 0x01; - -- result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); -+ result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); - if (result != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - -@@ -1363,9 +1372,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, - ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ - ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ - ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ -- ExtraDat->ovrflg = ExtBuf[0]; -- ExtraDat->mngflg = ExtBuf[1]; -- ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); -+ ExtraDat->ovrflg = bbuf[0]; -+ ExtraDat->mngflg = bbuf[1]; -+ ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); - - return USB_STOR_TRANSPORT_GOOD; - } -@@ -1569,9 +1578,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) - u16 PhyBlock, newblk, i; - u16 LogStart, LogEnde; - struct ms_lib_type_extdat extdat; -- u8 buf[0x200]; - u32 count = 0, index = 0; - struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -+ u8 *bbuf = info->bbuf; - - for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { - ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); -@@ -1585,14 +1594,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) - } - - if (count == PhyBlock) { -- ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf); -+ ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, -+ bbuf); - count += 0x80; - } - index = (PhyBlock % 0x80) * 4; - -- extdat.ovrflg = buf[index]; -- extdat.mngflg = buf[index+1]; -- extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]); -+ extdat.ovrflg = bbuf[index]; -+ extdat.mngflg = bbuf[index+1]; -+ extdat.logadr = memstick_logaddr(bbuf[index+2], -+ bbuf[index+3]); - - if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { - ms_lib_setacquired_errorblock(us, PhyBlock); -@@ -2075,9 +2086,9 @@ static int ene_ms_init(struct us_data *us) - { - struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; - int result; -- u8 buf[0x200]; - u16 MSP_BlockSize, MSP_UserAreaBlocks; - struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -+ u8 *bbuf = info->bbuf; - - printk(KERN_INFO "transport --- ENE_MSInit\n"); - -@@ -2096,13 +2107,13 @@ static int ene_ms_init(struct us_data *us) - bcb->CDB[0] = 0xF1; - bcb->CDB[1] = 0x01; - -- result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); -+ result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); - if (result != USB_STOR_XFER_GOOD) { - printk(KERN_ERR "Execution MS Init Code Fail !!\n"); - return USB_STOR_TRANSPORT_ERROR; - } - /* the same part to test ENE */ -- info->MS_Status = *(struct MS_STATUS *)&buf[0]; -+ info->MS_Status = *(struct MS_STATUS *) bbuf; - - if (info->MS_Status.Insert && info->MS_Status.Ready) { - printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert); -@@ -2111,15 +2122,15 @@ static int ene_ms_init(struct us_data *us) - printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG); - printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP); - if (info->MS_Status.IsMSPro) { -- MSP_BlockSize = (buf[6] << 8) | buf[7]; -- MSP_UserAreaBlocks = (buf[10] << 8) | buf[11]; -+ MSP_BlockSize = (bbuf[6] << 8) | bbuf[7]; -+ MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11]; - info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; - } else { - ms_card_init(us); /* Card is MS (to ms.c)*/ - } - usb_stor_dbg(us, "MS Init Code OK !!\n"); - } else { -- usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]); -+ usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]); - return USB_STOR_TRANSPORT_ERROR; - } - -@@ -2129,9 +2140,9 @@ static int ene_ms_init(struct us_data *us) - static int ene_sd_init(struct us_data *us) - { - int result; -- u8 buf[0x200]; - struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; - struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; -+ u8 *bbuf = info->bbuf; - - usb_stor_dbg(us, "transport --- ENE_SDInit\n"); - /* SD Init Part-1 */ -@@ -2165,17 +2176,17 @@ static int ene_sd_init(struct us_data *us) - bcb->Flags = US_BULK_FLAG_IN; - bcb->CDB[0] = 0xF1; - -- result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); -+ result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); - if (result != USB_STOR_XFER_GOOD) { - usb_stor_dbg(us, "Execution SD Init Code Fail !!\n"); - return USB_STOR_TRANSPORT_ERROR; - } - -- info->SD_Status = *(struct SD_STATUS *)&buf[0]; -+ info->SD_Status = *(struct SD_STATUS *) bbuf; - if (info->SD_Status.Insert && info->SD_Status.Ready) { - struct SD_STATUS *s = &info->SD_Status; - -- ene_get_card_status(us, (unsigned char *)&buf); -+ ene_get_card_status(us, bbuf); - usb_stor_dbg(us, "Insert = %x\n", s->Insert); - usb_stor_dbg(us, "Ready = %x\n", s->Ready); - usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC); -@@ -2183,7 +2194,7 @@ static int ene_sd_init(struct us_data *us) - usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed); - usb_stor_dbg(us, "WtP = %x\n", s->WtP); - } else { -- usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]); -+ usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]); - return USB_STOR_TRANSPORT_ERROR; - } - return USB_STOR_TRANSPORT_GOOD; -@@ -2193,13 +2204,15 @@ static int ene_sd_init(struct us_data *us) - static int ene_init(struct us_data *us) - { - int result; -- u8 misc_reg03 = 0; -+ u8 misc_reg03; - struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); -+ u8 *bbuf = info->bbuf; - -- result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); -+ result = ene_get_card_type(us, REG_CARD_STATUS, bbuf); - if (result != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; - -+ misc_reg03 = bbuf[0]; - if (misc_reg03 & 0x01) { - if (!info->SD_Status.Ready) { - result = ene_sd_init(us); -@@ -2316,8 +2329,9 @@ static int ene_ub6250_probe(struct usb_interface *intf, - const struct usb_device_id *id) - { - int result; -- u8 misc_reg03 = 0; -+ u8 misc_reg03; - struct us_data *us; -+ struct ene_ub6250_info *info; - - result = usb_stor_probe1(&us, intf, id, - (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list, -@@ -2326,11 +2340,16 @@ static int ene_ub6250_probe(struct usb_interface *intf, - return result; - - /* FIXME: where should the code alloc extra buf ? */ -- if (!us->extra) { -- us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); -- if (!us->extra) -- return -ENOMEM; -- us->extra_destructor = ene_ub6250_info_destructor; -+ us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); -+ if (!us->extra) -+ return -ENOMEM; -+ us->extra_destructor = ene_ub6250_info_destructor; -+ -+ info = (struct ene_ub6250_info *)(us->extra); -+ info->bbuf = kmalloc(512, GFP_KERNEL); -+ if (!info->bbuf) { -+ kfree(us->extra); -+ return -ENOMEM; - } - - us->transport_name = "ene_ub6250"; -@@ -2342,12 +2361,13 @@ static int ene_ub6250_probe(struct usb_interface *intf, - return result; - - /* probe card type */ -- result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); -+ result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf); - if (result != USB_STOR_XFER_GOOD) { - usb_stor_disconnect(intf); - return USB_STOR_TRANSPORT_ERROR; - } - -+ misc_reg03 = info->bbuf[0]; - if (!(misc_reg03 & 0x01)) { - pr_info("ums_eneub6250: This driver only supports SD/MS cards. " - "It does not support SM cards.\n"); -diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c -index 6345e85822a4..a50cf45e530f 100644 ---- a/drivers/uwb/i1480/dfu/usb.c -+++ b/drivers/uwb/i1480/dfu/usb.c -@@ -341,6 +341,7 @@ error_submit_ep1: - static - int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) - { -+ struct usb_device *udev = interface_to_usbdev(iface); - struct i1480_usb *i1480_usb; - struct i1480 *i1480; - struct device *dev = &iface->dev; -@@ -352,8 +353,8 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) - iface->cur_altsetting->desc.bInterfaceNumber); - goto error; - } -- if (iface->num_altsetting > 1 -- && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) { -+ if (iface->num_altsetting > 1 && -+ le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) { - /* Need altsetting #1 [HW QUIRK] or EP1 won't work */ - result = usb_set_interface(interface_to_usbdev(iface), 0, 1); - if (result < 0) -diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c -index 1a11aedc4fe8..9eb5b314ba06 100644 ---- a/drivers/watchdog/pcwd_usb.c -+++ b/drivers/watchdog/pcwd_usb.c -@@ -630,6 +630,9 @@ static int usb_pcwd_probe(struct usb_interface *interface, - return -ENODEV; - } - -+ if (iface_desc->desc.bNumEndpoints < 1) -+ return -ENODEV; -+ - /* check out the endpoint: it has to be Interrupt & IN */ - endpoint = &iface_desc->endpoint[0].desc; - -diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c -index 4d8caeb94a11..bdb9c94335f1 100644 ---- a/fs/ceph/acl.c -+++ b/fs/ceph/acl.c -@@ -128,7 +128,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) - if (new_mode != old_mode) { - newattrs.ia_mode = new_mode; - newattrs.ia_valid = ATTR_MODE; -- ret = ceph_setattr(dentry, &newattrs); -+ ret = __ceph_setattr(dentry, &newattrs); - if (ret) - goto out_dput; - } -@@ -138,7 +138,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) - if (new_mode != old_mode) { - newattrs.ia_mode = old_mode; - newattrs.ia_valid = ATTR_MODE; -- ceph_setattr(dentry, &newattrs); -+ __ceph_setattr(dentry, &newattrs); - } - goto out_dput; - } -diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c -index d98536c8abfc..9f0d99094cc1 100644 ---- a/fs/ceph/inode.c -+++ b/fs/ceph/inode.c -@@ -1773,7 +1773,7 @@ static const struct inode_operations ceph_symlink_iops = { - /* - * setattr - */ --int ceph_setattr(struct dentry *dentry, struct iattr *attr) -+int __ceph_setattr(struct dentry *dentry, struct iattr *attr) - { - struct inode *inode = d_inode(dentry); - struct ceph_inode_info *ci = ceph_inode(inode); -@@ -1975,11 +1975,6 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) - if (inode_dirty_flags) - __mark_inode_dirty(inode, inode_dirty_flags); - -- if (ia_valid & ATTR_MODE) { -- err = posix_acl_chmod(inode, attr->ia_mode); -- if (err) -- goto out_put; -- } - - if (mask) { - req->r_inode = inode; -@@ -1993,13 +1988,23 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) - ceph_cap_string(dirtied), mask); - - ceph_mdsc_put_request(req); -- if (mask & CEPH_SETATTR_SIZE) -- __ceph_do_pending_vmtruncate(inode); - ceph_free_cap_flush(prealloc_cf); -+ -+ if (err >= 0 && (mask & CEPH_SETATTR_SIZE)) -+ __ceph_do_pending_vmtruncate(inode); -+ - return err; --out_put: -- ceph_mdsc_put_request(req); -- ceph_free_cap_flush(prealloc_cf); -+} -+ -+int ceph_setattr(struct dentry *dentry, struct iattr *attr) -+{ -+ int err; -+ -+ err = __ceph_setattr(dentry, attr); -+ -+ if (err >= 0 && (attr->ia_valid & ATTR_MODE)) -+ err = posix_acl_chmod(d_inode(dentry), attr->ia_mode); -+ - return err; - } - -diff --git a/fs/ceph/super.h b/fs/ceph/super.h -index 75b7d125ce66..8c8cb8fe3d32 100644 ---- a/fs/ceph/super.h -+++ b/fs/ceph/super.h -@@ -788,6 +788,7 @@ static inline int ceph_do_getattr(struct inode *inode, int mask, bool force) - return __ceph_do_getattr(inode, NULL, mask, force); - } - extern int ceph_permission(struct inode *inode, int mask); -+extern int __ceph_setattr(struct dentry *dentry, struct iattr *attr); - extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); - extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat); -diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c -index 9d6c2dcf1bd0..f240cef8b326 100644 ---- a/fs/ext4/crypto.c -+++ b/fs/ext4/crypto.c -@@ -94,7 +94,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx) - * Return: An allocated and initialized encryption context on success; error - * value or NULL otherwise. - */ --struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode) -+struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode, -+ gfp_t gfp_flags) - { - struct ext4_crypto_ctx *ctx = NULL; - int res = 0; -@@ -121,7 +122,7 @@ struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode) - list_del(&ctx->free_list); - spin_unlock_irqrestore(&ext4_crypto_ctx_lock, flags); - if (!ctx) { -- ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, GFP_NOFS); -+ ctx = kmem_cache_zalloc(ext4_crypto_ctx_cachep, gfp_flags); - if (!ctx) { - res = -ENOMEM; - goto out; -@@ -258,7 +259,8 @@ static int ext4_page_crypto(struct inode *inode, - ext4_direction_t rw, - pgoff_t index, - struct page *src_page, -- struct page *dest_page) -+ struct page *dest_page, -+ gfp_t gfp_flags) - - { - u8 xts_tweak[EXT4_XTS_TWEAK_SIZE]; -@@ -269,7 +271,7 @@ static int ext4_page_crypto(struct inode *inode, - struct crypto_ablkcipher *tfm = ci->ci_ctfm; - int res = 0; - -- req = ablkcipher_request_alloc(tfm, GFP_NOFS); -+ req = ablkcipher_request_alloc(tfm, gfp_flags); - if (!req) { - printk_ratelimited(KERN_ERR - "%s: crypto_request_alloc() failed\n", -@@ -310,9 +312,10 @@ static int ext4_page_crypto(struct inode *inode, - return 0; - } - --static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx) -+static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx, -+ gfp_t gfp_flags) - { -- ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT); -+ ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, gfp_flags); - if (ctx->w.bounce_page == NULL) - return ERR_PTR(-ENOMEM); - ctx->flags |= EXT4_WRITE_PATH_FL; -@@ -335,7 +338,8 @@ static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx) - * error value or NULL. - */ - struct page *ext4_encrypt(struct inode *inode, -- struct page *plaintext_page) -+ struct page *plaintext_page, -+ gfp_t gfp_flags) - { - struct ext4_crypto_ctx *ctx; - struct page *ciphertext_page = NULL; -@@ -343,17 +347,17 @@ struct page *ext4_encrypt(struct inode *inode, - - BUG_ON(!PageLocked(plaintext_page)); - -- ctx = ext4_get_crypto_ctx(inode); -+ ctx = ext4_get_crypto_ctx(inode, gfp_flags); - if (IS_ERR(ctx)) - return (struct page *) ctx; - - /* The encryption operation will require a bounce page. */ -- ciphertext_page = alloc_bounce_page(ctx); -+ ciphertext_page = alloc_bounce_page(ctx, gfp_flags); - if (IS_ERR(ciphertext_page)) - goto errout; - ctx->w.control_page = plaintext_page; - err = ext4_page_crypto(inode, EXT4_ENCRYPT, plaintext_page->index, -- plaintext_page, ciphertext_page); -+ plaintext_page, ciphertext_page, gfp_flags); - if (err) { - ciphertext_page = ERR_PTR(err); - errout: -@@ -381,8 +385,8 @@ int ext4_decrypt(struct page *page) - { - BUG_ON(!PageLocked(page)); - -- return ext4_page_crypto(page->mapping->host, -- EXT4_DECRYPT, page->index, page, page); -+ return ext4_page_crypto(page->mapping->host, EXT4_DECRYPT, -+ page->index, page, page, GFP_NOFS); - } - - int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) -@@ -403,11 +407,11 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) - - BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE); - -- ctx = ext4_get_crypto_ctx(inode); -+ ctx = ext4_get_crypto_ctx(inode, GFP_NOFS); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - -- ciphertext_page = alloc_bounce_page(ctx); -+ ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT); - if (IS_ERR(ciphertext_page)) { - err = PTR_ERR(ciphertext_page); - goto errout; -@@ -415,11 +419,12 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex) - - while (len--) { - err = ext4_page_crypto(inode, EXT4_ENCRYPT, lblk, -- ZERO_PAGE(0), ciphertext_page); -+ ZERO_PAGE(0), ciphertext_page, -+ GFP_NOFS); - if (err) - goto errout; - -- bio = bio_alloc(GFP_KERNEL, 1); -+ bio = bio_alloc(GFP_NOWAIT, 1); - if (!bio) { - err = -ENOMEM; - goto errout; -diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c -index 2fbef8a14760..2cfe3ffc276f 100644 ---- a/fs/ext4/crypto_fname.c -+++ b/fs/ext4/crypto_fname.c -@@ -343,7 +343,7 @@ int _ext4_fname_disk_to_usr(struct inode *inode, - memcpy(buf+4, &hinfo->minor_hash, 4); - } else - memset(buf, 0, 8); -- memcpy(buf + 8, iname->name + iname->len - 16, 16); -+ memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16); - oname->name[0] = '_'; - ret = digest_encode(buf, 24, oname->name+1); - oname->len = ret + 1; -diff --git a/fs/ext4/crypto_policy.c b/fs/ext4/crypto_policy.c -index dd561f916f0b..e4f4fc4e56ab 100644 ---- a/fs/ext4/crypto_policy.c -+++ b/fs/ext4/crypto_policy.c -@@ -148,26 +148,38 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy) - int ext4_is_child_context_consistent_with_parent(struct inode *parent, - struct inode *child) - { -- struct ext4_crypt_info *parent_ci, *child_ci; -+ const struct ext4_crypt_info *parent_ci, *child_ci; -+ struct ext4_encryption_context parent_ctx, child_ctx; - int res; - -- if ((parent == NULL) || (child == NULL)) { -- pr_err("parent %p child %p\n", parent, child); -- WARN_ON(1); /* Should never happen */ -- return 0; -- } -- - /* No restrictions on file types which are never encrypted */ - if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && - !S_ISLNK(child->i_mode)) - return 1; - -- /* no restrictions if the parent directory is not encrypted */ -+ /* No restrictions if the parent directory is unencrypted */ - if (!ext4_encrypted_inode(parent)) - return 1; -- /* if the child directory is not encrypted, this is always a problem */ -+ -+ /* Encrypted directories must not contain unencrypted files */ - if (!ext4_encrypted_inode(child)) - return 0; -+ -+ /* -+ * Both parent and child are encrypted, so verify they use the same -+ * encryption policy. Compare the fscrypt_info structs if the keys are -+ * available, otherwise retrieve and compare the fscrypt_contexts. -+ * -+ * Note that the fscrypt_context retrieval will be required frequently -+ * when accessing an encrypted directory tree without the key. -+ * Performance-wise this is not a big deal because we already don't -+ * really optimize for file access without the key (to the extent that -+ * such access is even possible), given that any attempted access -+ * already causes a fscrypt_context retrieval and keyring search. -+ * -+ * In any case, if an unexpected error occurs, fall back to "forbidden". -+ */ -+ - res = ext4_get_encryption_info(parent); - if (res) - return 0; -@@ -176,17 +188,35 @@ int ext4_is_child_context_consistent_with_parent(struct inode *parent, - return 0; - parent_ci = EXT4_I(parent)->i_crypt_info; - child_ci = EXT4_I(child)->i_crypt_info; -- if (!parent_ci && !child_ci) -- return 1; -- if (!parent_ci || !child_ci) -+ if (parent_ci && child_ci) { -+ return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key, -+ EXT4_KEY_DESCRIPTOR_SIZE) == 0 && -+ (parent_ci->ci_data_mode == child_ci->ci_data_mode) && -+ (parent_ci->ci_filename_mode == -+ child_ci->ci_filename_mode) && -+ (parent_ci->ci_flags == child_ci->ci_flags); -+ } -+ -+ res = ext4_xattr_get(parent, EXT4_XATTR_INDEX_ENCRYPTION, -+ EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, -+ &parent_ctx, sizeof(parent_ctx)); -+ if (res != sizeof(parent_ctx)) -+ return 0; -+ -+ res = ext4_xattr_get(child, EXT4_XATTR_INDEX_ENCRYPTION, -+ EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, -+ &child_ctx, sizeof(child_ctx)); -+ if (res != sizeof(child_ctx)) - return 0; - -- return (memcmp(parent_ci->ci_master_key, -- child_ci->ci_master_key, -- EXT4_KEY_DESCRIPTOR_SIZE) == 0 && -- (parent_ci->ci_data_mode == child_ci->ci_data_mode) && -- (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && -- (parent_ci->ci_flags == child_ci->ci_flags)); -+ return memcmp(parent_ctx.master_key_descriptor, -+ child_ctx.master_key_descriptor, -+ EXT4_KEY_DESCRIPTOR_SIZE) == 0 && -+ (parent_ctx.contents_encryption_mode == -+ child_ctx.contents_encryption_mode) && -+ (parent_ctx.filenames_encryption_mode == -+ child_ctx.filenames_encryption_mode) && -+ (parent_ctx.flags == child_ctx.flags); - } - - /** -diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h -index 3de9bb357b4f..c8ad14c697c4 100644 ---- a/fs/ext4/ext4.h -+++ b/fs/ext4/ext4.h -@@ -2261,11 +2261,13 @@ extern struct kmem_cache *ext4_crypt_info_cachep; - bool ext4_valid_contents_enc_mode(uint32_t mode); - uint32_t ext4_validate_encryption_key_size(uint32_t mode, uint32_t size); - extern struct workqueue_struct *ext4_read_workqueue; --struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode); -+struct ext4_crypto_ctx *ext4_get_crypto_ctx(struct inode *inode, -+ gfp_t gfp_flags); - void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx); - void ext4_restore_control_page(struct page *data_page); - struct page *ext4_encrypt(struct inode *inode, -- struct page *plaintext_page); -+ struct page *plaintext_page, -+ gfp_t gfp_flags); - int ext4_decrypt(struct page *page); - int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex); - extern const struct dentry_operations ext4_encrypted_d_ops; -diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c -index fafa903ab3c0..1d007e853f5c 100644 ---- a/fs/ext4/namei.c -+++ b/fs/ext4/namei.c -@@ -1243,9 +1243,9 @@ static inline int ext4_match(struct ext4_filename *fname, - if (unlikely(!name)) { - if (fname->usr_fname->name[0] == '_') { - int ret; -- if (de->name_len < 16) -+ if (de->name_len <= 32) - return 0; -- ret = memcmp(de->name + de->name_len - 16, -+ ret = memcmp(de->name + ((de->name_len - 17) & ~15), - fname->crypto_buf.name + 8, 16); - return (ret == 0) ? 1 : 0; - } -diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c -index 17fbe3882b8e..6ca56f5f72b5 100644 ---- a/fs/ext4/page-io.c -+++ b/fs/ext4/page-io.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "ext4_jbd2.h" - #include "xattr.h" -@@ -485,9 +486,20 @@ int ext4_bio_write_page(struct ext4_io_submit *io, - - if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode) && - nr_to_submit) { -- data_page = ext4_encrypt(inode, page); -+ gfp_t gfp_flags = GFP_NOFS; -+ -+ retry_encrypt: -+ data_page = ext4_encrypt(inode, page, gfp_flags); - if (IS_ERR(data_page)) { - ret = PTR_ERR(data_page); -+ if (ret == -ENOMEM && wbc->sync_mode == WB_SYNC_ALL) { -+ if (io->io_bio) { -+ ext4_io_submit(io); -+ congestion_wait(BLK_RW_ASYNC, HZ/50); -+ } -+ gfp_flags |= __GFP_NOFAIL; -+ goto retry_encrypt; -+ } - data_page = NULL; - goto out; - } -diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c -index 5dc5e95063de..bc7642f57dc8 100644 ---- a/fs/ext4/readpage.c -+++ b/fs/ext4/readpage.c -@@ -279,7 +279,7 @@ int ext4_mpage_readpages(struct address_space *mapping, - - if (ext4_encrypted_inode(inode) && - S_ISREG(inode->i_mode)) { -- ctx = ext4_get_crypto_ctx(inode); -+ ctx = ext4_get_crypto_ctx(inode, GFP_NOFS); - if (IS_ERR(ctx)) - goto set_error_page; - } -diff --git a/fs/f2fs/crypto_fname.c b/fs/f2fs/crypto_fname.c -index ab377d496a39..38349ed5ea51 100644 ---- a/fs/f2fs/crypto_fname.c -+++ b/fs/f2fs/crypto_fname.c -@@ -333,7 +333,7 @@ int f2fs_fname_disk_to_usr(struct inode *inode, - memset(buf + 4, 0, 4); - } else - memset(buf, 0, 8); -- memcpy(buf + 8, iname->name + iname->len - 16, 16); -+ memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16); - oname->name[0] = '_'; - ret = digest_encode(buf, 24, oname->name + 1); - oname->len = ret + 1; -diff --git a/fs/f2fs/crypto_policy.c b/fs/f2fs/crypto_policy.c -index 5bbd1989d5e6..884f3f0fe29d 100644 ---- a/fs/f2fs/crypto_policy.c -+++ b/fs/f2fs/crypto_policy.c -@@ -141,25 +141,38 @@ int f2fs_get_policy(struct inode *inode, struct f2fs_encryption_policy *policy) - int f2fs_is_child_context_consistent_with_parent(struct inode *parent, - struct inode *child) - { -- struct f2fs_crypt_info *parent_ci, *child_ci; -+ const struct f2fs_crypt_info *parent_ci, *child_ci; -+ struct f2fs_encryption_context parent_ctx, child_ctx; - int res; - -- if ((parent == NULL) || (child == NULL)) { -- pr_err("parent %p child %p\n", parent, child); -- BUG_ON(1); -- } -- - /* No restrictions on file types which are never encrypted */ - if (!S_ISREG(child->i_mode) && !S_ISDIR(child->i_mode) && - !S_ISLNK(child->i_mode)) - return 1; - -- /* no restrictions if the parent directory is not encrypted */ -+ /* No restrictions if the parent directory is unencrypted */ - if (!f2fs_encrypted_inode(parent)) - return 1; -- /* if the child directory is not encrypted, this is always a problem */ -+ -+ /* Encrypted directories must not contain unencrypted files */ - if (!f2fs_encrypted_inode(child)) - return 0; -+ -+ /* -+ * Both parent and child are encrypted, so verify they use the same -+ * encryption policy. Compare the fscrypt_info structs if the keys are -+ * available, otherwise retrieve and compare the fscrypt_contexts. -+ * -+ * Note that the fscrypt_context retrieval will be required frequently -+ * when accessing an encrypted directory tree without the key. -+ * Performance-wise this is not a big deal because we already don't -+ * really optimize for file access without the key (to the extent that -+ * such access is even possible), given that any attempted access -+ * already causes a fscrypt_context retrieval and keyring search. -+ * -+ * In any case, if an unexpected error occurs, fall back to "forbidden". -+ */ -+ - res = f2fs_get_encryption_info(parent); - if (res) - return 0; -@@ -168,17 +181,35 @@ int f2fs_is_child_context_consistent_with_parent(struct inode *parent, - return 0; - parent_ci = F2FS_I(parent)->i_crypt_info; - child_ci = F2FS_I(child)->i_crypt_info; -- if (!parent_ci && !child_ci) -- return 1; -- if (!parent_ci || !child_ci) -+ if (parent_ci && child_ci) { -+ return memcmp(parent_ci->ci_master_key, child_ci->ci_master_key, -+ F2FS_KEY_DESCRIPTOR_SIZE) == 0 && -+ (parent_ci->ci_data_mode == child_ci->ci_data_mode) && -+ (parent_ci->ci_filename_mode == -+ child_ci->ci_filename_mode) && -+ (parent_ci->ci_flags == child_ci->ci_flags); -+ } -+ -+ res = f2fs_getxattr(parent, F2FS_XATTR_INDEX_ENCRYPTION, -+ F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, -+ &parent_ctx, sizeof(parent_ctx), NULL); -+ if (res != sizeof(parent_ctx)) -+ return 0; -+ -+ res = f2fs_getxattr(child, F2FS_XATTR_INDEX_ENCRYPTION, -+ F2FS_XATTR_NAME_ENCRYPTION_CONTEXT, -+ &child_ctx, sizeof(child_ctx), NULL); -+ if (res != sizeof(child_ctx)) - return 0; - -- return (memcmp(parent_ci->ci_master_key, -- child_ci->ci_master_key, -- F2FS_KEY_DESCRIPTOR_SIZE) == 0 && -- (parent_ci->ci_data_mode == child_ci->ci_data_mode) && -- (parent_ci->ci_filename_mode == child_ci->ci_filename_mode) && -- (parent_ci->ci_flags == child_ci->ci_flags)); -+ return memcmp(parent_ctx.master_key_descriptor, -+ child_ctx.master_key_descriptor, -+ F2FS_KEY_DESCRIPTOR_SIZE) == 0 && -+ (parent_ctx.contents_encryption_mode == -+ child_ctx.contents_encryption_mode) && -+ (parent_ctx.filenames_encryption_mode == -+ child_ctx.filenames_encryption_mode) && -+ (parent_ctx.flags == child_ctx.flags); - } - - /** -diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c -index 7c1678ba8f92..60972a559685 100644 ---- a/fs/f2fs/dir.c -+++ b/fs/f2fs/dir.c -@@ -124,19 +124,29 @@ struct f2fs_dir_entry *find_target_dentry(struct f2fs_filename *fname, - - de = &d->dentry[bit_pos]; - -- /* encrypted case */ -+ if (de->hash_code != namehash) -+ goto not_match; -+ - de_name.name = d->filename[bit_pos]; - de_name.len = le16_to_cpu(de->name_len); - -- /* show encrypted name */ -- if (fname->hash) { -- if (de->hash_code == fname->hash) -- goto found; -- } else if (de_name.len == name->len && -- de->hash_code == namehash && -- !memcmp(de_name.name, name->name, name->len)) -+#ifdef CONFIG_F2FS_FS_ENCRYPTION -+ if (unlikely(!name->name)) { -+ if (fname->usr_fname->name[0] == '_') { -+ if (de_name.len > 32 && -+ !memcmp(de_name.name + ((de_name.len - 17) & ~15), -+ fname->crypto_buf.name + 8, 16)) -+ goto found; -+ goto not_match; -+ } -+ name->name = fname->crypto_buf.name; -+ name->len = fname->crypto_buf.len; -+ } -+#endif -+ if (de_name.len == name->len && -+ !memcmp(de_name.name, name->name, name->len)) - goto found; -- -+not_match: - if (max_slots && max_len > *max_slots) - *max_slots = max_len; - max_len = 0; -@@ -170,7 +180,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, - int max_slots; - f2fs_hash_t namehash; - -- namehash = f2fs_dentry_hash(&name); -+ namehash = f2fs_dentry_hash(&name, fname); - - f2fs_bug_on(F2FS_I_SB(dir), level > MAX_DIR_HASH_DEPTH); - -@@ -547,7 +557,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, - - level = 0; - slots = GET_DENTRY_SLOTS(new_name.len); -- dentry_hash = f2fs_dentry_hash(&new_name); -+ dentry_hash = f2fs_dentry_hash(&new_name, NULL); - - current_depth = F2FS_I(dir)->i_current_depth; - if (F2FS_I(dir)->chash == dentry_hash) { -diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h -index b1aeca83f4be..2871576fbca4 100644 ---- a/fs/f2fs/f2fs.h -+++ b/fs/f2fs/f2fs.h -@@ -1722,7 +1722,8 @@ void f2fs_msg(struct super_block *, const char *, const char *, ...); - /* - * hash.c - */ --f2fs_hash_t f2fs_dentry_hash(const struct qstr *); -+f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, -+ struct f2fs_filename *fname); - - /* - * node.c -diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c -index 71b7206c431e..b238d2fec3e5 100644 ---- a/fs/f2fs/hash.c -+++ b/fs/f2fs/hash.c -@@ -70,7 +70,8 @@ static void str2hashbuf(const unsigned char *msg, size_t len, - *buf++ = pad; - } - --f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info) -+f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info, -+ struct f2fs_filename *fname) - { - __u32 hash; - f2fs_hash_t f2fs_hash; -@@ -79,6 +80,10 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info) - const unsigned char *name = name_info->name; - size_t len = name_info->len; - -+ /* encrypted bigname case */ -+ if (fname && !fname->disk_name.name) -+ return cpu_to_le32(fname->hash); -+ - if (is_dot_dotdot(name_info)) - return 0; - -diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c -index bda7126466c0..ad80f916b64d 100644 ---- a/fs/f2fs/inline.c -+++ b/fs/f2fs/inline.c -@@ -303,7 +303,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, - if (IS_ERR(ipage)) - return NULL; - -- namehash = f2fs_dentry_hash(&name); -+ namehash = f2fs_dentry_hash(&name, fname); - - inline_dentry = inline_data_addr(ipage); - -@@ -468,7 +468,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *name, - - f2fs_wait_on_page_writeback(ipage, NODE); - -- name_hash = f2fs_dentry_hash(name); -+ name_hash = f2fs_dentry_hash(name, NULL); - make_dentry_ptr(NULL, &d, (void *)dentry_blk, 2); - f2fs_update_dentry(ino, mode, &d, name, name_hash, bit_pos); - -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index 12935209deca..c3e1cb481fe0 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -4041,8 +4041,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr, - struct nfsd4_getdeviceinfo *gdev) - { - struct xdr_stream *xdr = &resp->xdr; -- const struct nfsd4_layout_ops *ops = -- nfsd4_layout_ops[gdev->gd_layout_type]; -+ const struct nfsd4_layout_ops *ops; - u32 starting_len = xdr->buf->len, needed_len; - __be32 *p; - -@@ -4059,6 +4058,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr, - - /* If maxcount is 0 then just update notifications */ - if (gdev->gd_maxcount != 0) { -+ ops = nfsd4_layout_ops[gdev->gd_layout_type]; - nfserr = ops->encode_getdeviceinfo(xdr, gdev); - if (nfserr) { - /* -@@ -4111,8 +4111,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr, - struct nfsd4_layoutget *lgp) - { - struct xdr_stream *xdr = &resp->xdr; -- const struct nfsd4_layout_ops *ops = -- nfsd4_layout_ops[lgp->lg_layout_type]; -+ const struct nfsd4_layout_ops *ops; - __be32 *p; - - dprintk("%s: err %d\n", __func__, nfserr); -@@ -4135,6 +4134,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr, - *p++ = cpu_to_be32(lgp->lg_seg.iomode); - *p++ = cpu_to_be32(lgp->lg_layout_type); - -+ ops = nfsd4_layout_ops[lgp->lg_layout_type]; - nfserr = ops->encode_layoutget(xdr, lgp); - out: - kfree(lgp->lg_content); -diff --git a/fs/proc/generic.c b/fs/proc/generic.c -index ff3ffc76a937..3773335791da 100644 ---- a/fs/proc/generic.c -+++ b/fs/proc/generic.c -@@ -469,6 +469,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name) - ent->data = NULL; - ent->proc_fops = NULL; - ent->proc_iops = NULL; -+ parent->nlink++; - if (proc_register(parent, ent) < 0) { - kfree(ent); - parent->nlink--; -diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h -index 8f6849084248..e23392517db9 100644 ---- a/include/linux/kprobes.h -+++ b/include/linux/kprobes.h -@@ -330,7 +330,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, - int write, void __user *buffer, - size_t *length, loff_t *ppos); - #endif -- -+extern void wait_for_kprobe_optimizer(void); -+#else -+static inline void wait_for_kprobe_optimizer(void) { } - #endif /* CONFIG_OPTPROBES */ - #ifdef CONFIG_KPROBES_ON_FTRACE - extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, -diff --git a/kernel/fork.c b/kernel/fork.c -index 278a2ddad351..0ee630f3ad4b 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -1590,11 +1590,13 @@ static struct task_struct *copy_process(unsigned long clone_flags, - */ - recalc_sigpending(); - if (signal_pending(current)) { -- spin_unlock(¤t->sighand->siglock); -- write_unlock_irq(&tasklist_lock); - retval = -ERESTARTNOINTR; - goto bad_fork_cancel_cgroup; - } -+ if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) { -+ retval = -ENOMEM; -+ goto bad_fork_cancel_cgroup; -+ } - - if (likely(p->pid)) { - ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); -@@ -1645,6 +1647,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, - return p; - - bad_fork_cancel_cgroup: -+ spin_unlock(¤t->sighand->siglock); -+ write_unlock_irq(&tasklist_lock); - cgroup_cancel_fork(p, cgrp_ss_priv); - bad_fork_free_pid: - threadgroup_change_end(current); -diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c -index 15206453b12a..e4453d9f788c 100644 ---- a/kernel/irq/chip.c -+++ b/kernel/irq/chip.c -@@ -810,8 +810,8 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, - if (!desc) - return; - -- __irq_do_set_handler(desc, handle, 1, NULL); - desc->irq_common_data.handler_data = data; -+ __irq_do_set_handler(desc, handle, 1, NULL); - - irq_put_desc_busunlock(desc, flags); - } -diff --git a/kernel/kprobes.c b/kernel/kprobes.c -index d10ab6b9b5e0..695763516908 100644 ---- a/kernel/kprobes.c -+++ b/kernel/kprobes.c -@@ -563,7 +563,7 @@ static void kprobe_optimizer(struct work_struct *work) - } - - /* Wait for completing optimization and unoptimization */ --static void wait_for_kprobe_optimizer(void) -+void wait_for_kprobe_optimizer(void) - { - mutex_lock(&kprobe_mutex); - -diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c -index a65ba137fd15..567ecc826bc8 100644 ---- a/kernel/pid_namespace.c -+++ b/kernel/pid_namespace.c -@@ -255,7 +255,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) - * if reparented. - */ - for (;;) { -- set_current_state(TASK_UNINTERRUPTIBLE); -+ set_current_state(TASK_INTERRUPTIBLE); - if (pid_ns->nr_hashed == init_pids) - break; - schedule(); -diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c -index 8f258f437ac2..812069b66f47 100644 ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -3918,6 +3918,26 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq) - if (!cfs_bandwidth_used()) - return; - -+ /* Synchronize hierarchical throttle counter: */ -+ if (unlikely(!cfs_rq->throttle_uptodate)) { -+ struct rq *rq = rq_of(cfs_rq); -+ struct cfs_rq *pcfs_rq; -+ struct task_group *tg; -+ -+ cfs_rq->throttle_uptodate = 1; -+ -+ /* Get closest up-to-date node, because leaves go first: */ -+ for (tg = cfs_rq->tg->parent; tg; tg = tg->parent) { -+ pcfs_rq = tg->cfs_rq[cpu_of(rq)]; -+ if (pcfs_rq->throttle_uptodate) -+ break; -+ } -+ if (tg) { -+ cfs_rq->throttle_count = pcfs_rq->throttle_count; -+ cfs_rq->throttled_clock_task = rq_clock_task(rq); -+ } -+ } -+ - /* an active group must be handled by the update_curr()->put() path */ - if (!cfs_rq->runtime_enabled || cfs_rq->curr) - return; -@@ -4233,15 +4253,14 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) - - /* Don't dequeue parent if it has other entities besides us */ - if (cfs_rq->load.weight) { -+ /* Avoid re-evaluating load for this entity: */ -+ se = parent_entity(se); - /* - * Bias pick_next to pick a task from this cfs_rq, as - * p is sleeping when it is within its sched_slice. - */ -- if (task_sleep && parent_entity(se)) -- set_next_buddy(parent_entity(se)); -- -- /* avoid re-evaluating load for this entity */ -- se = parent_entity(se); -+ if (task_sleep && se && !throttled_hierarchy(cfs_rq)) -+ set_next_buddy(se); - break; - } - flags |= DEQUEUE_SLEEP; -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 0517abd7dd73..4e5db65d1aab 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -417,7 +417,7 @@ struct cfs_rq { - - u64 throttled_clock, throttled_clock_task; - u64 throttled_clock_task_time; -- int throttled, throttle_count; -+ int throttled, throttle_count, throttle_uptodate; - struct list_head throttled_list; - #endif /* CONFIG_CFS_BANDWIDTH */ - #endif /* CONFIG_FAIR_GROUP_SCHED */ -diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c -index c9956440d0e6..12ea4ea619ee 100644 ---- a/kernel/trace/trace_kprobe.c -+++ b/kernel/trace/trace_kprobe.c -@@ -1471,6 +1471,11 @@ static __init int kprobe_trace_self_tests_init(void) - - end: - release_all_trace_kprobes(); -+ /* -+ * Wait for the optimizer work to finish. Otherwise it might fiddle -+ * with probes in already freed __init text. -+ */ -+ wait_for_kprobe_optimizer(); - if (warn) - pr_cont("NG: Some tests are failed. Please check them.\n"); - else -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 530e6427f823..47b469663822 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -1269,6 +1269,16 @@ out_unlock: - return ret; - } - -+/* -+ * FOLL_FORCE can write to even unwritable pmd's, but only -+ * after we've gone through a COW cycle and they are dirty. -+ */ -+static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags) -+{ -+ return pmd_write(pmd) || -+ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd)); -+} -+ - struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, - unsigned long addr, - pmd_t *pmd, -@@ -1279,7 +1289,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, - - assert_spin_locked(pmd_lockptr(mm, pmd)); - -- if (flags & FOLL_WRITE && !pmd_write(*pmd)) -+ if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, flags)) - goto out; - - /* Avoid dumping huge zero page */ -diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c -index 48d0dc89b58d..e735f781e4f3 100644 ---- a/net/ipx/af_ipx.c -+++ b/net/ipx/af_ipx.c -@@ -1168,11 +1168,10 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) - sipx->sipx_network = ipxif->if_netnum; - memcpy(sipx->sipx_node, ipxif->if_node, - sizeof(sipx->sipx_node)); -- rc = -EFAULT; -+ rc = 0; - if (copy_to_user(arg, &ifr, sizeof(ifr))) -- break; -+ rc = -EFAULT; - ipxitf_put(ipxif); -- rc = 0; - break; - } - case SIOCAIPXITFCRT: -diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c -index ed5a9c110b3a..9ce9d5003dcc 100644 ---- a/security/integrity/ima/ima_appraise.c -+++ b/security/integrity/ima/ima_appraise.c -@@ -203,10 +203,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, - - cause = "missing-hash"; - status = INTEGRITY_NOLABEL; -- if (opened & FILE_CREATED) { -+ if (opened & FILE_CREATED) - iint->flags |= IMA_NEW_FILE; -+ if ((iint->flags & IMA_NEW_FILE) && -+ !(iint->flags & IMA_DIGSIG_REQUIRED)) - status = INTEGRITY_PASS; -- } - goto out; - } - diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.70-71.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.70-71.patch deleted file mode 100644 index e72e5bfad..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.70-71.patch +++ /dev/null @@ -1,2294 +0,0 @@ -diff --git a/Makefile b/Makefile -index a5ecb29c6ed3..ad91a79aed51 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 70 -+SUBLEVEL = 71 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h -index 91b963a887b7..29c3b400f949 100644 ---- a/arch/sparc/include/asm/pgtable_32.h -+++ b/arch/sparc/include/asm/pgtable_32.h -@@ -91,9 +91,9 @@ extern unsigned long pfn_base; - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ --extern unsigned long empty_zero_page; -+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; - --#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page)) -+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) - - /* - * In general all page table modifications should use the V8 atomic -diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h -index 29d64b1758ed..be0cc1beed41 100644 ---- a/arch/sparc/include/asm/setup.h -+++ b/arch/sparc/include/asm/setup.h -@@ -16,7 +16,7 @@ extern char reboot_command[]; - */ - extern unsigned char boot_cpu_id; - --extern unsigned long empty_zero_page; -+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; - - extern int serial_console; - static inline int con_is_present(void) -diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c -index eb8287155279..3b7092d9ea8f 100644 ---- a/arch/sparc/mm/init_32.c -+++ b/arch/sparc/mm/init_32.c -@@ -301,7 +301,7 @@ void __init mem_init(void) - - - /* Saves us work later. */ -- memset((void *)&empty_zero_page, 0, PAGE_SIZE); -+ memset((void *)empty_zero_page, 0, PAGE_SIZE); - - i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5); - i += 1; -diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c -index fc061f7c2bd1..a7de8ae185a5 100644 ---- a/drivers/char/pcmcia/cm4040_cs.c -+++ b/drivers/char/pcmcia/cm4040_cs.c -@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, - - rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); - if (rc <= 0) { -- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); -+ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); - DEBUGP(2, dev, "<- cm4040_write (failed)\n"); - if (rc == -ERESTARTSYS) - return rc; -@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, - for (i = 0; i < bytes_to_write; i++) { - rc = wait_for_bulk_out_ready(dev); - if (rc <= 0) { -- DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", -+ DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n", - rc); - DEBUGP(2, dev, "<- cm4040_write (failed)\n"); - if (rc == -ERESTARTSYS) -@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, - rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); - - if (rc <= 0) { -- DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); -+ DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc); - DEBUGP(2, dev, "<- cm4040_write (failed)\n"); - if (rc == -ERESTARTSYS) - return rc; -diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c -index ce0645d0c1e5..61e3a097a478 100644 ---- a/drivers/gpu/drm/gma500/psb_intel_lvds.c -+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c -@@ -783,20 +783,23 @@ void psb_intel_lvds_init(struct drm_device *dev, - if (scan->type & DRM_MODE_TYPE_PREFERRED) { - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, scan); -+ DRM_DEBUG_KMS("Using mode from DDC\n"); - goto out; /* FIXME: check for quirks */ - } - } - - /* Failed to get EDID, what about VBT? do we need this? */ -- if (mode_dev->vbt_mode) -+ if (dev_priv->lfp_lvds_vbt_mode) { - mode_dev->panel_fixed_mode = -- drm_mode_duplicate(dev, mode_dev->vbt_mode); -+ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); - -- if (!mode_dev->panel_fixed_mode) -- if (dev_priv->lfp_lvds_vbt_mode) -- mode_dev->panel_fixed_mode = -- drm_mode_duplicate(dev, -- dev_priv->lfp_lvds_vbt_mode); -+ if (mode_dev->panel_fixed_mode) { -+ mode_dev->panel_fixed_mode->type |= -+ DRM_MODE_TYPE_PREFERRED; -+ DRM_DEBUG_KMS("Using mode from VBT\n"); -+ goto out; -+ } -+ } - - /* - * If we didn't get EDID, try checking if the panel is already turned -@@ -813,6 +816,7 @@ void psb_intel_lvds_init(struct drm_device *dev, - if (mode_dev->panel_fixed_mode) { - mode_dev->panel_fixed_mode->type |= - DRM_MODE_TYPE_PREFERRED; -+ DRM_DEBUG_KMS("Using pre-programmed mode\n"); - goto out; /* FIXME: check for quirks */ - } - } -diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c -index 4a09947be244..3c32f095a873 100644 ---- a/drivers/gpu/drm/radeon/ci_dpm.c -+++ b/drivers/gpu/drm/radeon/ci_dpm.c -@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev) - u32 vblank_time = r600_dpm_get_vblank_time(rdev); - u32 switch_limit = pi->mem_gddr5 ? 450 : 300; - -+ /* disable mclk switching if the refresh is >120Hz, even if the -+ * blanking period would allow it -+ */ -+ if (r600_dpm_get_vrefresh(rdev) > 120) -+ return true; -+ - if (vblank_time < switch_limit) - return true; - else -diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c -index f81fb2641097..134874cab4c7 100644 ---- a/drivers/gpu/drm/radeon/cik.c -+++ b/drivers/gpu/drm/radeon/cik.c -@@ -7762,7 +7762,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -@@ -7792,7 +7792,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_RX_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 32491355a1d4..ba9e6ed4ae54 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -4924,7 +4924,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -@@ -4955,7 +4955,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_RX_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c -index cc2fdf0be37a..0e20c08f8977 100644 ---- a/drivers/gpu/drm/radeon/r600.c -+++ b/drivers/gpu/drm/radeon/r600.c -@@ -3945,7 +3945,7 @@ static void r600_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c -index f878d6962da5..5cf3a2cbc07e 100644 ---- a/drivers/gpu/drm/radeon/si.c -+++ b/drivers/gpu/drm/radeon/si.c -@@ -6335,7 +6335,7 @@ static inline void si_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -@@ -6366,7 +6366,7 @@ static inline void si_irq_ack(struct radeon_device *rdev) - WREG32(DC_HPD5_INT_CONTROL, tmp); - } - if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { -- tmp = RREG32(DC_HPD5_INT_CONTROL); -+ tmp = RREG32(DC_HPD6_INT_CONTROL); - tmp |= DC_HPDx_RX_INT_ACK; - WREG32(DC_HPD6_INT_CONTROL, tmp); - } -diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c -index 35e3fd9fadf6..b62c50d1b1e4 100644 ---- a/drivers/hid/wacom_wac.c -+++ b/drivers/hid/wacom_wac.c -@@ -1440,37 +1440,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) - { - unsigned char *data = wacom->data; - -- if (wacom->pen_input) -+ if (wacom->pen_input) { - dev_dbg(wacom->pen_input->dev.parent, - "%s: received report #%d\n", __func__, data[0]); -- else if (wacom->touch_input) -+ -+ if (len == WACOM_PKGLEN_PENABLED || -+ data[0] == WACOM_REPORT_PENABLED) -+ return wacom_tpc_pen(wacom); -+ } -+ else if (wacom->touch_input) { - dev_dbg(wacom->touch_input->dev.parent, - "%s: received report #%d\n", __func__, data[0]); - -- switch (len) { -- case WACOM_PKGLEN_TPC1FG: -- return wacom_tpc_single_touch(wacom, len); -+ switch (len) { -+ case WACOM_PKGLEN_TPC1FG: -+ return wacom_tpc_single_touch(wacom, len); - -- case WACOM_PKGLEN_TPC2FG: -- return wacom_tpc_mt_touch(wacom); -+ case WACOM_PKGLEN_TPC2FG: -+ return wacom_tpc_mt_touch(wacom); - -- case WACOM_PKGLEN_PENABLED: -- return wacom_tpc_pen(wacom); -+ default: -+ switch (data[0]) { -+ case WACOM_REPORT_TPC1FG: -+ case WACOM_REPORT_TPCHID: -+ case WACOM_REPORT_TPCST: -+ case WACOM_REPORT_TPC1FGE: -+ return wacom_tpc_single_touch(wacom, len); - -- default: -- switch (data[0]) { -- case WACOM_REPORT_TPC1FG: -- case WACOM_REPORT_TPCHID: -- case WACOM_REPORT_TPCST: -- case WACOM_REPORT_TPC1FGE: -- return wacom_tpc_single_touch(wacom, len); -- -- case WACOM_REPORT_TPCMT: -- case WACOM_REPORT_TPCMT2: -- return wacom_mt_touch(wacom); -+ case WACOM_REPORT_TPCMT: -+ case WACOM_REPORT_TPCMT2: -+ return wacom_mt_touch(wacom); - -- case WACOM_REPORT_PENABLED: -- return wacom_tpc_pen(wacom); -+ } - } - } - -diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c -index 0ed77eeff31e..a2e3dd715380 100644 ---- a/drivers/i2c/busses/i2c-tiny-usb.c -+++ b/drivers/i2c/busses/i2c-tiny-usb.c -@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len) - { - struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; -+ void *dmadata = kmalloc(len, GFP_KERNEL); -+ int ret; -+ -+ if (!dmadata) -+ return -ENOMEM; - - /* do control transfer */ -- return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), -+ ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), - cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | -- USB_DIR_IN, value, index, data, len, 2000); -+ USB_DIR_IN, value, index, dmadata, len, 2000); -+ -+ memcpy(data, dmadata, len); -+ kfree(dmadata); -+ return ret; - } - - static int usb_write(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len) - { - struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; -+ void *dmadata = kmemdup(data, len, GFP_KERNEL); -+ int ret; -+ -+ if (!dmadata) -+ return -ENOMEM; - - /* do control transfer */ -- return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), -+ ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), - cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, -- value, index, data, len, 2000); -+ value, index, dmadata, len, 2000); -+ -+ kfree(dmadata); -+ return ret; - } - - static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev) -diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c -index 3b423b0ad8e7..f280744578e4 100644 ---- a/drivers/mmc/host/sdhci-iproc.c -+++ b/drivers/mmc/host/sdhci-iproc.c -@@ -156,7 +156,8 @@ static const struct sdhci_ops sdhci_iproc_ops = { - }; - - static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = { -- .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, -+ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | -+ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, - .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN, - .ops = &sdhci_iproc_ops, - }; -diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c -index 8a1d9fffd7d6..26255862d1cf 100644 ---- a/drivers/net/ethernet/emulex/benet/be_main.c -+++ b/drivers/net/ethernet/emulex/benet/be_main.c -@@ -5260,9 +5260,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb, - struct be_adapter *adapter = netdev_priv(dev); - u8 l4_hdr = 0; - -- /* The code below restricts offload features for some tunneled packets. -+ /* The code below restricts offload features for some tunneled and -+ * Q-in-Q packets. - * Offload features for normal (non tunnel) packets are unchanged. - */ -+ features = vlan_features_check(skb, features); - if (!skb->encapsulation || - !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS)) - return features; -diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c -index 0240552b50f3..d2701c53ed68 100644 ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -203,34 +203,6 @@ static int marvell_config_aneg(struct phy_device *phydev) - { - int err; - -- /* The Marvell PHY has an errata which requires -- * that certain registers get written in order -- * to restart autonegotiation */ -- err = phy_write(phydev, MII_BMCR, BMCR_RESET); -- -- if (err < 0) -- return err; -- -- err = phy_write(phydev, 0x1d, 0x1f); -- if (err < 0) -- return err; -- -- err = phy_write(phydev, 0x1e, 0x200c); -- if (err < 0) -- return err; -- -- err = phy_write(phydev, 0x1d, 0x5); -- if (err < 0) -- return err; -- -- err = phy_write(phydev, 0x1e, 0); -- if (err < 0) -- return err; -- -- err = phy_write(phydev, 0x1e, 0x100); -- if (err < 0) -- return err; -- - err = marvell_set_polarity(phydev, phydev->mdix); - if (err < 0) - return err; -@@ -264,6 +236,42 @@ static int marvell_config_aneg(struct phy_device *phydev) - return 0; - } - -+static int m88e1101_config_aneg(struct phy_device *phydev) -+{ -+ int err; -+ -+ /* This Marvell PHY has an errata which requires -+ * that certain registers get written in order -+ * to restart autonegotiation -+ */ -+ err = phy_write(phydev, MII_BMCR, BMCR_RESET); -+ -+ if (err < 0) -+ return err; -+ -+ err = phy_write(phydev, 0x1d, 0x1f); -+ if (err < 0) -+ return err; -+ -+ err = phy_write(phydev, 0x1e, 0x200c); -+ if (err < 0) -+ return err; -+ -+ err = phy_write(phydev, 0x1d, 0x5); -+ if (err < 0) -+ return err; -+ -+ err = phy_write(phydev, 0x1e, 0); -+ if (err < 0) -+ return err; -+ -+ err = phy_write(phydev, 0x1e, 0x100); -+ if (err < 0) -+ return err; -+ -+ return marvell_config_aneg(phydev); -+} -+ - #ifdef CONFIG_OF_MDIO - /* - * Set and/or override some configuration registers based on the -@@ -993,7 +1001,7 @@ static struct phy_driver marvell_drivers[] = { - .name = "Marvell 88E1101", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, -- .config_aneg = &marvell_config_aneg, -+ .config_aneg = &m88e1101_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index c6f5d9a6bec6..582d8f0c6266 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -730,6 +730,8 @@ static const struct usb_device_id products[] = { - {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */ - {QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */ -+ {QMI_FIXED_INTF(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */ -+ {QMI_FIXED_INTF(0x1199, 0x907b, 10)}, /* Sierra Wireless EM74xx */ - {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ - {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ - {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ -diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c -index 0e2a19e58923..7f7c87762bc6 100644 ---- a/drivers/net/virtio_net.c -+++ b/drivers/net/virtio_net.c -@@ -1415,6 +1415,7 @@ static const struct net_device_ops virtnet_netdev = { - #ifdef CONFIG_NET_RX_BUSY_POLL - .ndo_busy_poll = virtnet_busy_poll, - #endif -+ .ndo_features_check = passthru_features_check, - }; - - static void virtnet_config_changed_work(struct work_struct *work) -diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h -index 1766a20ebcb1..741f3ee81cfe 100644 ---- a/drivers/s390/net/qeth_core.h -+++ b/drivers/s390/net/qeth_core.h -@@ -717,6 +717,7 @@ enum qeth_discipline_id { - }; - - struct qeth_discipline { -+ const struct device_type *devtype; - void (*start_poll)(struct ccw_device *, int, unsigned long); - qdio_handler_t *input_handler; - qdio_handler_t *output_handler; -@@ -881,6 +882,9 @@ extern struct qeth_discipline qeth_l2_discipline; - extern struct qeth_discipline qeth_l3_discipline; - extern const struct attribute_group *qeth_generic_attr_groups[]; - extern const struct attribute_group *qeth_osn_attr_groups[]; -+extern const struct attribute_group qeth_device_attr_group; -+extern const struct attribute_group qeth_device_blkt_group; -+extern const struct device_type qeth_generic_devtype; - extern struct workqueue_struct *qeth_wq; - - int qeth_card_hw_is_reachable(struct qeth_card *); -diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c -index 31ac53fa5cee..d10bf3da8e5f 100644 ---- a/drivers/s390/net/qeth_core_main.c -+++ b/drivers/s390/net/qeth_core_main.c -@@ -5449,10 +5449,12 @@ void qeth_core_free_discipline(struct qeth_card *card) - card->discipline = NULL; - } - --static const struct device_type qeth_generic_devtype = { -+const struct device_type qeth_generic_devtype = { - .name = "qeth_generic", - .groups = qeth_generic_attr_groups, - }; -+EXPORT_SYMBOL_GPL(qeth_generic_devtype); -+ - static const struct device_type qeth_osn_devtype = { - .name = "qeth_osn", - .groups = qeth_osn_attr_groups, -@@ -5578,23 +5580,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) - goto err_card; - } - -- if (card->info.type == QETH_CARD_TYPE_OSN) -- gdev->dev.type = &qeth_osn_devtype; -- else -- gdev->dev.type = &qeth_generic_devtype; -- - switch (card->info.type) { - case QETH_CARD_TYPE_OSN: - case QETH_CARD_TYPE_OSM: - rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); - if (rc) - goto err_card; -+ -+ gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN) -+ ? card->discipline->devtype -+ : &qeth_osn_devtype; - rc = card->discipline->setup(card->gdev); - if (rc) - goto err_disc; -- case QETH_CARD_TYPE_OSD: -- case QETH_CARD_TYPE_OSX: -+ break; - default: -+ gdev->dev.type = &qeth_generic_devtype; - break; - } - -@@ -5650,8 +5651,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) - if (rc) - goto err; - rc = card->discipline->setup(card->gdev); -- if (rc) -+ if (rc) { -+ qeth_core_free_discipline(card); - goto err; -+ } - } - rc = card->discipline->set_online(gdev); - err: -diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c -index e6e5b9671bf2..fa844b0ff847 100644 ---- a/drivers/s390/net/qeth_core_sys.c -+++ b/drivers/s390/net/qeth_core_sys.c -@@ -409,12 +409,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, - - if (card->options.layer2 == newdis) - goto out; -- else { -- card->info.mac_bits = 0; -- if (card->discipline) { -- card->discipline->remove(card->gdev); -- qeth_core_free_discipline(card); -- } -+ if (card->info.type == QETH_CARD_TYPE_OSM) { -+ /* fixed layer, can't switch */ -+ rc = -EOPNOTSUPP; -+ goto out; -+ } -+ -+ card->info.mac_bits = 0; -+ if (card->discipline) { -+ card->discipline->remove(card->gdev); -+ qeth_core_free_discipline(card); - } - - rc = qeth_core_load_discipline(card, newdis); -@@ -422,6 +426,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, - goto out; - - rc = card->discipline->setup(card->gdev); -+ if (rc) -+ qeth_core_free_discipline(card); - out: - mutex_unlock(&card->discipline_mutex); - return rc ? rc : count; -@@ -699,10 +705,11 @@ static struct attribute *qeth_blkt_device_attrs[] = { - &dev_attr_inter_jumbo.attr, - NULL, - }; --static struct attribute_group qeth_device_blkt_group = { -+const struct attribute_group qeth_device_blkt_group = { - .name = "blkt", - .attrs = qeth_blkt_device_attrs, - }; -+EXPORT_SYMBOL_GPL(qeth_device_blkt_group); - - static struct attribute *qeth_device_attrs[] = { - &dev_attr_state.attr, -@@ -722,9 +729,10 @@ static struct attribute *qeth_device_attrs[] = { - &dev_attr_switch_attrs.attr, - NULL, - }; --static struct attribute_group qeth_device_attr_group = { -+const struct attribute_group qeth_device_attr_group = { - .attrs = qeth_device_attrs, - }; -+EXPORT_SYMBOL_GPL(qeth_device_attr_group); - - const struct attribute_group *qeth_generic_attr_groups[] = { - &qeth_device_attr_group, -diff --git a/drivers/s390/net/qeth_l2.h b/drivers/s390/net/qeth_l2.h -index 0767556404bd..eb87bf97d38a 100644 ---- a/drivers/s390/net/qeth_l2.h -+++ b/drivers/s390/net/qeth_l2.h -@@ -8,6 +8,8 @@ - - #include "qeth_core.h" - -+extern const struct attribute_group *qeth_l2_attr_groups[]; -+ - int qeth_l2_create_device_attributes(struct device *); - void qeth_l2_remove_device_attributes(struct device *); - void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card); -diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c -index df036b872b05..bf1e0e39334d 100644 ---- a/drivers/s390/net/qeth_l2_main.c -+++ b/drivers/s390/net/qeth_l2_main.c -@@ -1027,11 +1027,21 @@ static int qeth_l2_stop(struct net_device *dev) - return 0; - } - -+static const struct device_type qeth_l2_devtype = { -+ .name = "qeth_layer2", -+ .groups = qeth_l2_attr_groups, -+}; -+ - static int qeth_l2_probe_device(struct ccwgroup_device *gdev) - { - struct qeth_card *card = dev_get_drvdata(&gdev->dev); -+ int rc; - -- qeth_l2_create_device_attributes(&gdev->dev); -+ if (gdev->dev.type == &qeth_generic_devtype) { -+ rc = qeth_l2_create_device_attributes(&gdev->dev); -+ if (rc) -+ return rc; -+ } - INIT_LIST_HEAD(&card->vid_list); - hash_init(card->mac_htable); - card->options.layer2 = 1; -@@ -1043,7 +1053,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) - { - struct qeth_card *card = dev_get_drvdata(&cgdev->dev); - -- qeth_l2_remove_device_attributes(&cgdev->dev); -+ if (cgdev->dev.type == &qeth_generic_devtype) -+ qeth_l2_remove_device_attributes(&cgdev->dev); - qeth_set_allowed_threads(card, 0, 1); - wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); - -@@ -1101,7 +1112,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) - case QETH_CARD_TYPE_OSN: - card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN, - ether_setup); -- card->dev->flags |= IFF_NOARP; - break; - default: - card->dev = alloc_etherdev(0); -@@ -1114,9 +1124,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) - card->dev->watchdog_timeo = QETH_TX_TIMEOUT; - card->dev->mtu = card->info.initial_mtu; - card->dev->netdev_ops = &qeth_l2_netdev_ops; -- card->dev->ethtool_ops = -- (card->info.type != QETH_CARD_TYPE_OSN) ? -- &qeth_l2_ethtool_ops : &qeth_l2_osn_ops; -+ if (card->info.type == QETH_CARD_TYPE_OSN) { -+ card->dev->ethtool_ops = &qeth_l2_osn_ops; -+ card->dev->flags |= IFF_NOARP; -+ } else { -+ card->dev->ethtool_ops = &qeth_l2_ethtool_ops; -+ } - card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) { - card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM; -@@ -1429,6 +1442,7 @@ static int qeth_l2_control_event(struct qeth_card *card, - } - - struct qeth_discipline qeth_l2_discipline = { -+ .devtype = &qeth_l2_devtype, - .start_poll = qeth_qdio_start_poll, - .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, - .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, -diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c -index 692db49e3d2a..a48ed9e7e168 100644 ---- a/drivers/s390/net/qeth_l2_sys.c -+++ b/drivers/s390/net/qeth_l2_sys.c -@@ -272,3 +272,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) - } else - qeth_bridgeport_an_set(card, 0); - } -+ -+const struct attribute_group *qeth_l2_attr_groups[] = { -+ &qeth_device_attr_group, -+ &qeth_device_blkt_group, -+ /* l2 specific, see l2_{create,remove}_device_attributes(): */ -+ &qeth_l2_bridgeport_attr_group, -+ NULL, -+}; -diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c -index cc4d3c3d8cc5..285fe0b2c753 100644 ---- a/drivers/s390/net/qeth_l3_main.c -+++ b/drivers/s390/net/qeth_l3_main.c -@@ -3227,8 +3227,11 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) - static int qeth_l3_probe_device(struct ccwgroup_device *gdev) - { - struct qeth_card *card = dev_get_drvdata(&gdev->dev); -+ int rc; - -- qeth_l3_create_device_attributes(&gdev->dev); -+ rc = qeth_l3_create_device_attributes(&gdev->dev); -+ if (rc) -+ return rc; - card->options.layer2 = 0; - card->info.hwtrap = 0; - return 0; -@@ -3519,6 +3522,7 @@ static int qeth_l3_control_event(struct qeth_card *card, - } - - struct qeth_discipline qeth_l3_discipline = { -+ .devtype = &qeth_generic_devtype, - .start_poll = qeth_qdio_start_poll, - .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, - .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, -diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -index 8a5fbdb45cfd..e333029e4b6c 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c -+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c -@@ -4452,6 +4452,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) - struct MPT3SAS_DEVICE *sas_device_priv_data; - u32 response_code = 0; - unsigned long flags; -+ unsigned int sector_sz; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); -@@ -4510,6 +4511,20 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) - } - - xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); -+ -+ /* In case of bogus fw or device, we could end up having -+ * unaligned partial completion. We can force alignment here, -+ * then scsi-ml does not need to handle this misbehavior. -+ */ -+ sector_sz = scmd->device->sector_size; -+ if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz && -+ xfer_cnt % sector_sz)) { -+ sdev_printk(KERN_INFO, scmd->device, -+ "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n", -+ xfer_cnt, sector_sz); -+ xfer_cnt = round_down(xfer_cnt, sector_sz); -+ } -+ - scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) - log_info = le32_to_cpu(mpi_reply->IOCLogInfo); -diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c -index 119c2422aac7..75884aecf920 100644 ---- a/fs/xfs/libxfs/xfs_bmap.c -+++ b/fs/xfs/libxfs/xfs_bmap.c -@@ -2179,8 +2179,10 @@ xfs_bmap_add_extent_delay_real( - } - temp = xfs_bmap_worst_indlen(bma->ip, temp); - temp2 = xfs_bmap_worst_indlen(bma->ip, temp2); -- diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - -- (bma->cur ? bma->cur->bc_private.b.allocated : 0)); -+ diff = (int)(temp + temp2 - -+ (startblockval(PREV.br_startblock) - -+ (bma->cur ? -+ bma->cur->bc_private.b.allocated : 0))); - if (diff > 0) { - error = xfs_mod_fdblocks(bma->ip->i_mount, - -((int64_t)diff), false); -@@ -2232,7 +2234,6 @@ xfs_bmap_add_extent_delay_real( - temp = da_new; - if (bma->cur) - temp += bma->cur->bc_private.b.allocated; -- ASSERT(temp <= da_old); - if (temp < da_old) - xfs_mod_fdblocks(bma->ip->i_mount, - (int64_t)(da_old - temp), false); -diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c -index af1bbee5586e..28bc5e78b110 100644 ---- a/fs/xfs/libxfs/xfs_btree.c -+++ b/fs/xfs/libxfs/xfs_btree.c -@@ -4064,7 +4064,7 @@ xfs_btree_change_owner( - xfs_btree_readahead_ptr(cur, ptr, 1); - - /* save for the next iteration of the loop */ -- lptr = *ptr; -+ xfs_btree_copy_ptrs(cur, &lptr, ptr, 1); - } - - /* for each buffer in the level */ -diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h -index dd4824589470..234331227c0c 100644 ---- a/fs/xfs/xfs_attr.h -+++ b/fs/xfs/xfs_attr.h -@@ -112,6 +112,7 @@ typedef struct attrlist_cursor_kern { - *========================================================================*/ - - -+/* Return 0 on success, or -errno; other state communicated via *context */ - typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int, - unsigned char *, int, int, unsigned char *); - -diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c -index 4fa14820e2e2..c8be331a3196 100644 ---- a/fs/xfs/xfs_attr_list.c -+++ b/fs/xfs/xfs_attr_list.c -@@ -108,16 +108,14 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) - (int)sfe->namelen, - (int)sfe->valuelen, - &sfe->nameval[sfe->namelen]); -- -+ if (error) -+ return error; - /* - * Either search callback finished early or - * didn't fit it all in the buffer after all. - */ - if (context->seen_enough) - break; -- -- if (error) -- return error; - sfe = XFS_ATTR_SF_NEXTENTRY(sfe); - } - trace_xfs_attr_list_sf_all(context); -@@ -581,7 +579,7 @@ xfs_attr_put_listent( - trace_xfs_attr_list_full(context); - alist->al_more = 1; - context->seen_enough = 1; -- return 1; -+ return 0; - } - - aep = (attrlist_ent_t *)&context->alist[context->firstu]; -diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c -index 832764ee035a..863e1bff403b 100644 ---- a/fs/xfs/xfs_bmap_util.c -+++ b/fs/xfs/xfs_bmap_util.c -@@ -682,7 +682,7 @@ xfs_getbmap( - * extents. - */ - if (map[i].br_startblock == DELAYSTARTBLOCK && -- map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip))) -+ map[i].br_startoff < XFS_B_TO_FSB(mp, XFS_ISIZE(ip))) - ASSERT((iflags & BMV_IF_DELALLOC) != 0); - - if (map[i].br_startblock == HOLESTARTBLOCK && -diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c -index 8146b0cf20ce..dcb70969ff1c 100644 ---- a/fs/xfs/xfs_buf.c -+++ b/fs/xfs/xfs_buf.c -@@ -979,6 +979,8 @@ void - xfs_buf_unlock( - struct xfs_buf *bp) - { -+ ASSERT(xfs_buf_islocked(bp)); -+ - XB_CLEAR_OWNER(bp); - up(&bp->b_sema); - -@@ -1713,6 +1715,28 @@ error: - } - - /* -+ * Cancel a delayed write list. -+ * -+ * Remove each buffer from the list, clear the delwri queue flag and drop the -+ * associated buffer reference. -+ */ -+void -+xfs_buf_delwri_cancel( -+ struct list_head *list) -+{ -+ struct xfs_buf *bp; -+ -+ while (!list_empty(list)) { -+ bp = list_first_entry(list, struct xfs_buf, b_list); -+ -+ xfs_buf_lock(bp); -+ bp->b_flags &= ~_XBF_DELWRI_Q; -+ list_del_init(&bp->b_list); -+ xfs_buf_relse(bp); -+ } -+} -+ -+/* - * Add a buffer to the delayed write list. - * - * This queues a buffer for writeout if it hasn't already been. Note that -diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h -index c75721acd867..149bbd451731 100644 ---- a/fs/xfs/xfs_buf.h -+++ b/fs/xfs/xfs_buf.h -@@ -304,6 +304,7 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, - extern void *xfs_buf_offset(struct xfs_buf *, size_t); - - /* Delayed Write Buffer Routines */ -+extern void xfs_buf_delwri_cancel(struct list_head *); - extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *); - extern int xfs_buf_delwri_submit(struct list_head *); - extern int xfs_buf_delwri_submit_nowait(struct list_head *); -diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c -index 642d55d10075..2fbf643fa10a 100644 ---- a/fs/xfs/xfs_dir2_readdir.c -+++ b/fs/xfs/xfs_dir2_readdir.c -@@ -406,6 +406,7 @@ xfs_dir2_leaf_readbuf( - - /* - * Do we need more readahead? -+ * Each loop tries to process 1 full dir blk; last may be partial. - */ - blk_start_plug(&plug); - for (mip->ra_index = mip->ra_offset = i = 0; -@@ -416,7 +417,8 @@ xfs_dir2_leaf_readbuf( - * Read-ahead a contiguous directory block. - */ - if (i > mip->ra_current && -- map[mip->ra_index].br_blockcount >= geo->fsbcount) { -+ (map[mip->ra_index].br_blockcount - mip->ra_offset) >= -+ geo->fsbcount) { - xfs_dir3_data_readahead(dp, - map[mip->ra_index].br_startoff + mip->ra_offset, - XFS_FSB_TO_DADDR(dp->i_mount, -@@ -437,14 +439,19 @@ xfs_dir2_leaf_readbuf( - } - - /* -- * Advance offset through the mapping table. -+ * Advance offset through the mapping table, processing a full -+ * dir block even if it is fragmented into several extents. -+ * But stop if we have consumed all valid mappings, even if -+ * it's not yet a full directory block. - */ -- for (j = 0; j < geo->fsbcount; j += length ) { -+ for (j = 0; -+ j < geo->fsbcount && mip->ra_index < mip->map_valid; -+ j += length ) { - /* - * The rest of this extent but not more than a dir - * block. - */ -- length = min_t(int, geo->fsbcount, -+ length = min_t(int, geo->fsbcount - j, - map[mip->ra_index].br_blockcount - - mip->ra_offset); - mip->ra_offset += length; -diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c -index f5392ab2def1..ceea444dafb4 100644 ---- a/fs/xfs/xfs_file.c -+++ b/fs/xfs/xfs_file.c -@@ -1208,7 +1208,7 @@ xfs_find_get_desired_pgoff( - unsigned nr_pages; - unsigned int i; - -- want = min_t(pgoff_t, end - index, PAGEVEC_SIZE); -+ want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1; - nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, - want); - /* -@@ -1235,17 +1235,6 @@ xfs_find_get_desired_pgoff( - break; - } - -- /* -- * At lease we found one page. If this is the first time we -- * step into the loop, and if the first page index offset is -- * greater than the given search offset, a hole was found. -- */ -- if (type == HOLE_OFF && lastoff == startoff && -- lastoff < page_offset(pvec.pages[0])) { -- found = true; -- break; -- } -- - for (i = 0; i < nr_pages; i++) { - struct page *page = pvec.pages[i]; - loff_t b_offset; -@@ -1257,18 +1246,18 @@ xfs_find_get_desired_pgoff( - * file mapping. However, page->index will not change - * because we have a reference on the page. - * -- * Searching done if the page index is out of range. -- * If the current offset is not reaches the end of -- * the specified search range, there should be a hole -- * between them. -+ * If current page offset is beyond where we've ended, -+ * we've found a hole. - */ -- if (page->index > end) { -- if (type == HOLE_OFF && lastoff < endoff) { -- *offset = lastoff; -- found = true; -- } -+ if (type == HOLE_OFF && lastoff < endoff && -+ lastoff < page_offset(pvec.pages[i])) { -+ found = true; -+ *offset = lastoff; - goto out; - } -+ /* Searching done if the page index is out of range. */ -+ if (page->index > end) -+ goto out; - - lock_page(page); - /* -diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c -index d7a490f24ead..adbc1f59969a 100644 ---- a/fs/xfs/xfs_icache.c -+++ b/fs/xfs/xfs_icache.c -@@ -210,14 +210,17 @@ xfs_iget_cache_hit( - - error = inode_init_always(mp->m_super, inode); - if (error) { -+ bool wake; - /* - * Re-initializing the inode failed, and we are in deep - * trouble. Try to re-add it to the reclaim list. - */ - rcu_read_lock(); - spin_lock(&ip->i_flags_lock); -- -+ wake = !!__xfs_iflags_test(ip, XFS_INEW); - ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); -+ if (wake) -+ wake_up_bit(&ip->i_flags, __XFS_INEW_BIT); - ASSERT(ip->i_flags & XFS_IRECLAIMABLE); - trace_xfs_iget_reclaim_fail(ip); - goto out_error; -@@ -363,6 +366,22 @@ out_destroy: - return error; - } - -+static void -+xfs_inew_wait( -+ struct xfs_inode *ip) -+{ -+ wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT); -+ DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT); -+ -+ do { -+ prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE); -+ if (!xfs_iflags_test(ip, XFS_INEW)) -+ break; -+ schedule(); -+ } while (true); -+ finish_wait(wq, &wait.wait); -+} -+ - /* - * Look up an inode by number in the given file system. - * The inode is looked up in the cache held in each AG. -@@ -467,9 +486,11 @@ out_error_or_again: - - STATIC int - xfs_inode_ag_walk_grab( -- struct xfs_inode *ip) -+ struct xfs_inode *ip, -+ int flags) - { - struct inode *inode = VFS_I(ip); -+ bool newinos = !!(flags & XFS_AGITER_INEW_WAIT); - - ASSERT(rcu_read_lock_held()); - -@@ -487,7 +508,8 @@ xfs_inode_ag_walk_grab( - goto out_unlock_noent; - - /* avoid new or reclaimable inodes. Leave for reclaim code to flush */ -- if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM)) -+ if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) || -+ __xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM)) - goto out_unlock_noent; - spin_unlock(&ip->i_flags_lock); - -@@ -515,7 +537,8 @@ xfs_inode_ag_walk( - void *args), - int flags, - void *args, -- int tag) -+ int tag, -+ int iter_flags) - { - uint32_t first_index; - int last_error = 0; -@@ -557,7 +580,7 @@ restart: - for (i = 0; i < nr_found; i++) { - struct xfs_inode *ip = batch[i]; - -- if (done || xfs_inode_ag_walk_grab(ip)) -+ if (done || xfs_inode_ag_walk_grab(ip, iter_flags)) - batch[i] = NULL; - - /* -@@ -585,6 +608,9 @@ restart: - for (i = 0; i < nr_found; i++) { - if (!batch[i]) - continue; -+ if ((iter_flags & XFS_AGITER_INEW_WAIT) && -+ xfs_iflags_test(batch[i], XFS_INEW)) -+ xfs_inew_wait(batch[i]); - error = execute(batch[i], flags, args); - IRELE(batch[i]); - if (error == -EAGAIN) { -@@ -637,12 +663,13 @@ xfs_eofblocks_worker( - } - - int --xfs_inode_ag_iterator( -+xfs_inode_ag_iterator_flags( - struct xfs_mount *mp, - int (*execute)(struct xfs_inode *ip, int flags, - void *args), - int flags, -- void *args) -+ void *args, -+ int iter_flags) - { - struct xfs_perag *pag; - int error = 0; -@@ -652,7 +679,8 @@ xfs_inode_ag_iterator( - ag = 0; - while ((pag = xfs_perag_get(mp, ag))) { - ag = pag->pag_agno + 1; -- error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1); -+ error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1, -+ iter_flags); - xfs_perag_put(pag); - if (error) { - last_error = error; -@@ -664,6 +692,17 @@ xfs_inode_ag_iterator( - } - - int -+xfs_inode_ag_iterator( -+ struct xfs_mount *mp, -+ int (*execute)(struct xfs_inode *ip, int flags, -+ void *args), -+ int flags, -+ void *args) -+{ -+ return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0); -+} -+ -+int - xfs_inode_ag_iterator_tag( - struct xfs_mount *mp, - int (*execute)(struct xfs_inode *ip, int flags, -@@ -680,7 +719,8 @@ xfs_inode_ag_iterator_tag( - ag = 0; - while ((pag = xfs_perag_get_tag(mp, ag, tag))) { - ag = pag->pag_agno + 1; -- error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag); -+ error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag, -+ 0); - xfs_perag_put(pag); - if (error) { - last_error = error; -diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h -index 62f1f91c32cb..147a79212e63 100644 ---- a/fs/xfs/xfs_icache.h -+++ b/fs/xfs/xfs_icache.h -@@ -48,6 +48,11 @@ struct xfs_eofblocks { - #define XFS_IGET_UNTRUSTED 0x2 - #define XFS_IGET_DONTCACHE 0x4 - -+/* -+ * flags for AG inode iterator -+ */ -+#define XFS_AGITER_INEW_WAIT 0x1 /* wait on new inodes */ -+ - int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino, - uint flags, uint lock_flags, xfs_inode_t **ipp); - -@@ -72,6 +77,9 @@ void xfs_eofblocks_worker(struct work_struct *); - int xfs_inode_ag_iterator(struct xfs_mount *mp, - int (*execute)(struct xfs_inode *ip, int flags, void *args), - int flags, void *args); -+int xfs_inode_ag_iterator_flags(struct xfs_mount *mp, -+ int (*execute)(struct xfs_inode *ip, int flags, void *args), -+ int flags, void *args, int iter_flags); - int xfs_inode_ag_iterator_tag(struct xfs_mount *mp, - int (*execute)(struct xfs_inode *ip, int flags, void *args), - int flags, void *args, int tag); -diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h -index ca9e11989cbd..ae1a49845744 100644 ---- a/fs/xfs/xfs_inode.h -+++ b/fs/xfs/xfs_inode.h -@@ -208,7 +208,8 @@ xfs_get_initial_prid(struct xfs_inode *dp) - #define XFS_IRECLAIM (1 << 0) /* started reclaiming this inode */ - #define XFS_ISTALE (1 << 1) /* inode has been staled */ - #define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */ --#define XFS_INEW (1 << 3) /* inode has just been allocated */ -+#define __XFS_INEW_BIT 3 /* inode has just been allocated */ -+#define XFS_INEW (1 << __XFS_INEW_BIT) - #define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */ - #define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */ - #define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */ -@@ -453,6 +454,7 @@ static inline void xfs_finish_inode_setup(struct xfs_inode *ip) - xfs_iflags_clear(ip, XFS_INEW); - barrier(); - unlock_new_inode(VFS_I(ip)); -+ wake_up_bit(&ip->i_flags, __XFS_INEW_BIT); - } - - static inline void xfs_setup_existing_inode(struct xfs_inode *ip) -diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c -index d42738deec6d..e4a4f82ea13f 100644 ---- a/fs/xfs/xfs_ioctl.c -+++ b/fs/xfs/xfs_ioctl.c -@@ -403,6 +403,7 @@ xfs_attrlist_by_handle( - { - int error = -ENOMEM; - attrlist_cursor_kern_t *cursor; -+ struct xfs_fsop_attrlist_handlereq __user *p = arg; - xfs_fsop_attrlist_handlereq_t al_hreq; - struct dentry *dentry; - char *kbuf; -@@ -435,6 +436,11 @@ xfs_attrlist_by_handle( - if (error) - goto out_kfree; - -+ if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) { -+ error = -EFAULT; -+ goto out_kfree; -+ } -+ - if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) - error = -EFAULT; - -@@ -1379,10 +1385,11 @@ xfs_ioc_getbmap( - unsigned int cmd, - void __user *arg) - { -- struct getbmapx bmx; -+ struct getbmapx bmx = { 0 }; - int error; - -- if (copy_from_user(&bmx, arg, sizeof(struct getbmapx))) -+ /* struct getbmap is a strict subset of struct getbmapx. */ -+ if (copy_from_user(&bmx, arg, offsetof(struct getbmapx, bmv_iflags))) - return -EFAULT; - - if (bmx.bmv_count < 2) -diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c -index 532ab79d38fe..572b64a135b3 100644 ---- a/fs/xfs/xfs_qm.c -+++ b/fs/xfs/xfs_qm.c -@@ -1355,12 +1355,7 @@ xfs_qm_quotacheck( - mp->m_qflags |= flags; - - error_return: -- while (!list_empty(&buffer_list)) { -- struct xfs_buf *bp = -- list_first_entry(&buffer_list, struct xfs_buf, b_list); -- list_del_init(&bp->b_list); -- xfs_buf_relse(bp); -- } -+ xfs_buf_delwri_cancel(&buffer_list); - - if (error) { - xfs_warn(mp, -diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c -index 3640c6e896af..4d334440bd94 100644 ---- a/fs/xfs/xfs_qm_syscalls.c -+++ b/fs/xfs/xfs_qm_syscalls.c -@@ -764,5 +764,6 @@ xfs_qm_dqrele_all_inodes( - uint flags) - { - ASSERT(mp->m_quotainfo); -- xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL); -+ xfs_inode_ag_iterator_flags(mp, xfs_dqrele_inode, flags, NULL, -+ XFS_AGITER_INEW_WAIT); - } -diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c -index 839b35ca21c6..e6dae28dfa1a 100644 ---- a/fs/xfs/xfs_xattr.c -+++ b/fs/xfs/xfs_xattr.c -@@ -180,7 +180,7 @@ xfs_xattr_put_listent( - arraytop = context->count + prefix_len + namelen + 1; - if (arraytop > context->firstu) { - context->count = -1; /* insufficient space */ -- return 1; -+ return 0; - } - offset = (char *)context->alist + context->count; - strncpy(offset, xfs_xattr_prefix(flags), prefix_len); -@@ -222,12 +222,15 @@ list_one_attr(const char *name, const size_t len, void *data, - } - - ssize_t --xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) -+xfs_vn_listxattr( -+ struct dentry *dentry, -+ char *data, -+ size_t size) - { - struct xfs_attr_list_context context; - struct attrlist_cursor_kern cursor = { 0 }; -- struct inode *inode = d_inode(dentry); -- int error; -+ struct inode *inode = d_inode(dentry); -+ int error; - - /* - * First read the regular on-disk attributes. -@@ -245,7 +248,9 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) - else - context.put_listent = xfs_xattr_put_listent_sizes; - -- xfs_attr_list_int(&context); -+ error = xfs_attr_list_int(&context); -+ if (error) -+ return error; - if (context.count < 0) - return -ERANGE; - -diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h -index 67ce5bd3b56a..19db03dbbd00 100644 ---- a/include/linux/if_vlan.h -+++ b/include/linux/if_vlan.h -@@ -616,15 +616,16 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) - static inline netdev_features_t vlan_features_check(const struct sk_buff *skb, - netdev_features_t features) - { -- if (skb_vlan_tagged_multi(skb)) -- features = netdev_intersect_features(features, -- NETIF_F_SG | -- NETIF_F_HIGHDMA | -- NETIF_F_FRAGLIST | -- NETIF_F_GEN_CSUM | -- NETIF_F_HW_VLAN_CTAG_TX | -- NETIF_F_HW_VLAN_STAG_TX); -- -+ if (skb_vlan_tagged_multi(skb)) { -+ /* In the case of multi-tagged packets, use a direct mask -+ * instead of using netdev_interesect_features(), to make -+ * sure that only devices supporting NETIF_F_HW_CSUM will -+ * have checksum offloading support. -+ */ -+ features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | -+ NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX | -+ NETIF_F_HW_VLAN_STAG_TX; -+ } - return features; - } - -diff --git a/include/net/dst.h b/include/net/dst.h -index c7329dcd90cc..e4f450617919 100644 ---- a/include/net/dst.h -+++ b/include/net/dst.h -@@ -110,10 +110,16 @@ struct dst_entry { - }; - }; - -+struct dst_metrics { -+ u32 metrics[RTAX_MAX]; -+ atomic_t refcnt; -+}; -+extern const struct dst_metrics dst_default_metrics; -+ - u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); --extern const u32 dst_default_metrics[]; - - #define DST_METRICS_READ_ONLY 0x1UL -+#define DST_METRICS_REFCOUNTED 0x2UL - #define DST_METRICS_FLAGS 0x3UL - #define __DST_METRICS_PTR(Y) \ - ((u32 *)((Y) & ~DST_METRICS_FLAGS)) -diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h -index 3f98233388fb..bda1721e9622 100644 ---- a/include/net/ip_fib.h -+++ b/include/net/ip_fib.h -@@ -112,11 +112,11 @@ struct fib_info { - unsigned char fib_type; - __be32 fib_prefsrc; - u32 fib_priority; -- u32 *fib_metrics; --#define fib_mtu fib_metrics[RTAX_MTU-1] --#define fib_window fib_metrics[RTAX_WINDOW-1] --#define fib_rtt fib_metrics[RTAX_RTT-1] --#define fib_advmss fib_metrics[RTAX_ADVMSS-1] -+ struct dst_metrics *fib_metrics; -+#define fib_mtu fib_metrics->metrics[RTAX_MTU-1] -+#define fib_window fib_metrics->metrics[RTAX_WINDOW-1] -+#define fib_rtt fib_metrics->metrics[RTAX_RTT-1] -+#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] - int fib_nhs; - #ifdef CONFIG_IP_ROUTE_MULTIPATH - int fib_weight; -diff --git a/mm/memory-failure.c b/mm/memory-failure.c -index 750b7893ee3a..43aee7ab143e 100644 ---- a/mm/memory-failure.c -+++ b/mm/memory-failure.c -@@ -1619,12 +1619,8 @@ static int soft_offline_huge_page(struct page *page, int flags) - if (ret) { - pr_info("soft offline: %#lx: migration failed %d, type %lx\n", - pfn, ret, page->flags); -- /* -- * We know that soft_offline_huge_page() tries to migrate -- * only one hugepage pointed to by hpage, so we need not -- * run through the pagelist here. -- */ -- putback_active_hugepage(hpage); -+ if (!list_empty(&pagelist)) -+ putback_movable_pages(&pagelist); - if (ret > 0) - ret = -EIO; - } else { -diff --git a/mm/mlock.c b/mm/mlock.c -index d6006b146fea..9d2e773f3a95 100644 ---- a/mm/mlock.c -+++ b/mm/mlock.c -@@ -277,7 +277,7 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) - { - int i; - int nr = pagevec_count(pvec); -- int delta_munlocked; -+ int delta_munlocked = -nr; - struct pagevec pvec_putback; - int pgrescued = 0; - -@@ -297,6 +297,8 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) - continue; - else - __munlock_isolation_failed(page); -+ } else { -+ delta_munlocked++; - } - - /* -@@ -308,7 +310,6 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) - pagevec_add(&pvec_putback, pvec->pages[i]); - pvec->pages[i] = NULL; - } -- delta_munlocked = -nr + pagevec_count(&pvec_putback); - __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); - spin_unlock_irq(&zone->lru_lock); - -diff --git a/mm/slub.c b/mm/slub.c -index 65d5f92d51d2..4cf3a9c768b1 100644 ---- a/mm/slub.c -+++ b/mm/slub.c -@@ -5261,6 +5261,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) - char mbuf[64]; - char *buf; - struct slab_attribute *attr = to_slab_attr(slab_attrs[i]); -+ ssize_t len; - - if (!attr || !attr->store || !attr->show) - continue; -@@ -5285,8 +5286,9 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) - buf = buffer; - } - -- attr->show(root_cache, buf); -- attr->store(s, buf, strlen(buf)); -+ len = attr->show(root_cache, buf); -+ if (len > 0) -+ attr->store(s, buf, len); - } - - if (buffer) -diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c -index 413d18e37083..ff8bb41d713f 100644 ---- a/net/bridge/br_netlink.c -+++ b/net/bridge/br_netlink.c -@@ -768,6 +768,13 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[]) - return -EPROTONOSUPPORT; - } - } -+ -+ if (data[IFLA_BR_VLAN_DEFAULT_PVID]) { -+ __u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]); -+ -+ if (defpvid >= VLAN_VID_MASK) -+ return -EINVAL; -+ } - #endif - - return 0; -diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c -index 8a7ada8bb947..57be733a99bc 100644 ---- a/net/bridge/br_stp_if.c -+++ b/net/bridge/br_stp_if.c -@@ -166,6 +166,7 @@ static void br_stp_start(struct net_bridge *br) - br_debug(br, "using kernel STP\n"); - - /* To start timers on any ports left in blocking */ -+ mod_timer(&br->hello_timer, jiffies + br->hello_time); - br_port_state_selection(br); - } - -diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c -index 5f0f5af0ec35..7dbe6a5c31eb 100644 ---- a/net/bridge/br_stp_timer.c -+++ b/net/bridge/br_stp_timer.c -@@ -40,7 +40,7 @@ static void br_hello_timer_expired(unsigned long arg) - if (br->dev->flags & IFF_UP) { - br_config_bpdu_generation(br); - -- if (br->stp_enabled != BR_USER_STP) -+ if (br->stp_enabled == BR_KERNEL_STP) - mod_timer(&br->hello_timer, - round_jiffies(jiffies + br->hello_time)); - } -diff --git a/net/core/dst.c b/net/core/dst.c -index a1656e3b8d72..d7ad628bf64e 100644 ---- a/net/core/dst.c -+++ b/net/core/dst.c -@@ -151,13 +151,13 @@ int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb) - } - EXPORT_SYMBOL(dst_discard_out); - --const u32 dst_default_metrics[RTAX_MAX + 1] = { -+const struct dst_metrics dst_default_metrics = { - /* This initializer is needed to force linker to place this variable - * into const section. Otherwise it might end into bss section. - * We really want to avoid false sharing on this variable, and catch - * any writes on it. - */ -- [RTAX_MAX] = 0xdeadbeef, -+ .refcnt = ATOMIC_INIT(1), - }; - - void dst_init(struct dst_entry *dst, struct dst_ops *ops, -@@ -169,7 +169,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops, - if (dev) - dev_hold(dev); - dst->ops = ops; -- dst_init_metrics(dst, dst_default_metrics, true); -+ dst_init_metrics(dst, dst_default_metrics.metrics, true); - dst->expires = 0UL; - dst->path = dst; - dst->from = NULL; -@@ -315,25 +315,30 @@ EXPORT_SYMBOL(dst_release); - - u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old) - { -- u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC); -+ struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC); - - if (p) { -- u32 *old_p = __DST_METRICS_PTR(old); -+ struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old); - unsigned long prev, new; - -- memcpy(p, old_p, sizeof(u32) * RTAX_MAX); -+ atomic_set(&p->refcnt, 1); -+ memcpy(p->metrics, old_p->metrics, sizeof(p->metrics)); - - new = (unsigned long) p; - prev = cmpxchg(&dst->_metrics, old, new); - - if (prev != old) { - kfree(p); -- p = __DST_METRICS_PTR(prev); -+ p = (struct dst_metrics *)__DST_METRICS_PTR(prev); - if (prev & DST_METRICS_READ_ONLY) - p = NULL; -+ } else if (prev & DST_METRICS_REFCOUNTED) { -+ if (atomic_dec_and_test(&old_p->refcnt)) -+ kfree(old_p); - } - } -- return p; -+ BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0); -+ return (u32 *)p; - } - EXPORT_SYMBOL(dst_cow_metrics_generic); - -@@ -342,7 +347,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old) - { - unsigned long prev, new; - -- new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY; -+ new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY; - prev = cmpxchg(&dst->_metrics, old, new); - if (prev == old) - kfree(__DST_METRICS_PTR(old)); -diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index fe38ef58997c..d43544ce7550 100644 ---- a/net/core/rtnetlink.c -+++ b/net/core/rtnetlink.c -@@ -1458,13 +1458,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) - cb->nlh->nlmsg_seq, 0, - NLM_F_MULTI, - ext_filter_mask); -- /* If we ran out of room on the first message, -- * we're in trouble -- */ -- WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); - -- if (err < 0) -- goto out; -+ if (err < 0) { -+ if (likely(skb->len)) -+ goto out; -+ -+ goto out_err; -+ } - - nl_dump_check_consistent(cb, nlmsg_hdr(skb)); - cont: -@@ -1472,10 +1472,12 @@ cont: - } - } - out: -+ err = skb->len; -+out_err: - cb->args[1] = idx; - cb->args[0] = h; - -- return skb->len; -+ return err; - } - - int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len) -@@ -3127,8 +3129,12 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) - err = br_dev->netdev_ops->ndo_bridge_getlink( - skb, portid, seq, dev, - filter_mask, NLM_F_MULTI); -- if (err < 0 && err != -EOPNOTSUPP) -- break; -+ if (err < 0 && err != -EOPNOTSUPP) { -+ if (likely(skb->len)) -+ break; -+ -+ goto out_err; -+ } - } - idx++; - } -@@ -3139,16 +3145,22 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) - seq, dev, - filter_mask, - NLM_F_MULTI); -- if (err < 0 && err != -EOPNOTSUPP) -- break; -+ if (err < 0 && err != -EOPNOTSUPP) { -+ if (likely(skb->len)) -+ break; -+ -+ goto out_err; -+ } - } - idx++; - } - } -+ err = skb->len; -+out_err: - rcu_read_unlock(); - cb->args[0] = idx; - -- return skb->len; -+ return err; - } - - static inline size_t bridge_nlmsg_size(void) -diff --git a/net/core/sock.c b/net/core/sock.c -index 9c708a5fb751..bd2fad27891e 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -1690,17 +1690,17 @@ EXPORT_SYMBOL(skb_set_owner_w); - - void skb_orphan_partial(struct sk_buff *skb) - { -- /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc, -- * so we do not completely orphan skb, but transfert all -- * accounted bytes but one, to avoid unexpected reorders. -- */ - if (skb->destructor == sock_wfree - #ifdef CONFIG_INET - || skb->destructor == tcp_wfree - #endif - ) { -- atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc); -- skb->truesize = 1; -+ struct sock *sk = skb->sk; -+ -+ if (atomic_inc_not_zero(&sk->sk_refcnt)) { -+ atomic_sub(skb->truesize, &sk->sk_wmem_alloc); -+ skb->destructor = sock_efree; -+ } - } else { - skb_orphan(skb); - } -diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c -index 8113ad58fcb4..3470ad1843bb 100644 ---- a/net/dccp/ipv6.c -+++ b/net/dccp/ipv6.c -@@ -422,6 +422,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, - newsk->sk_backlog_rcv = dccp_v4_do_rcv; - newnp->pktoptions = NULL; - newnp->opt = NULL; -+ newnp->ipv6_mc_list = NULL; -+ newnp->ipv6_ac_list = NULL; -+ newnp->ipv6_fl_list = NULL; - newnp->mcast_oif = inet6_iif(skb); - newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; - -@@ -486,6 +489,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, - /* Clone RX bits */ - newnp->rxopt.all = np->rxopt.all; - -+ newnp->ipv6_mc_list = NULL; -+ newnp->ipv6_ac_list = NULL; -+ newnp->ipv6_fl_list = NULL; - newnp->pktoptions = NULL; - newnp->opt = NULL; - newnp->mcast_oif = inet6_iif(skb); -diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c -index 1adba44f8fbc..66dcb529fd9c 100644 ---- a/net/ipv4/fib_frontend.c -+++ b/net/ipv4/fib_frontend.c -@@ -757,7 +757,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) - unsigned int e = 0, s_e; - struct fib_table *tb; - struct hlist_head *head; -- int dumped = 0; -+ int dumped = 0, err; - - if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && - ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) -@@ -777,20 +777,27 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) - if (dumped) - memset(&cb->args[2], 0, sizeof(cb->args) - - 2 * sizeof(cb->args[0])); -- if (fib_table_dump(tb, skb, cb) < 0) -- goto out; -+ err = fib_table_dump(tb, skb, cb); -+ if (err < 0) { -+ if (likely(skb->len)) -+ goto out; -+ -+ goto out_err; -+ } - dumped = 1; - next: - e++; - } - } - out: -+ err = skb->len; -+out_err: - rcu_read_unlock(); - - cb->args[1] = e; - cb->args[0] = h; - -- return skb->len; -+ return err; - } - - /* Prepare and feed intra-kernel routing request. -diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c -index 67d44aa9e09f..b2504712259f 100644 ---- a/net/ipv4/fib_semantics.c -+++ b/net/ipv4/fib_semantics.c -@@ -204,6 +204,7 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp) - static void free_fib_info_rcu(struct rcu_head *head) - { - struct fib_info *fi = container_of(head, struct fib_info, rcu); -+ struct dst_metrics *m; - - change_nexthops(fi) { - if (nexthop_nh->nh_dev) -@@ -214,8 +215,9 @@ static void free_fib_info_rcu(struct rcu_head *head) - rt_fibinfo_free(&nexthop_nh->nh_rth_input); - } endfor_nexthops(fi); - -- if (fi->fib_metrics != (u32 *) dst_default_metrics) -- kfree(fi->fib_metrics); -+ m = fi->fib_metrics; -+ if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt)) -+ kfree(m); - kfree(fi); - } - -@@ -982,11 +984,11 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg) - val = 255; - if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) - return -EINVAL; -- fi->fib_metrics[type - 1] = val; -+ fi->fib_metrics->metrics[type - 1] = val; - } - - if (ecn_ca) -- fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; -+ fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA; - - return 0; - } -@@ -1044,11 +1046,12 @@ struct fib_info *fib_create_info(struct fib_config *cfg) - goto failure; - fib_info_cnt++; - if (cfg->fc_mx) { -- fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); -+ fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL); - if (!fi->fib_metrics) - goto failure; -+ atomic_set(&fi->fib_metrics->refcnt, 1); - } else -- fi->fib_metrics = (u32 *) dst_default_metrics; -+ fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; - - fi->fib_net = net; - fi->fib_protocol = cfg->fc_protocol; -@@ -1251,7 +1254,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event, - if (fi->fib_priority && - nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority)) - goto nla_put_failure; -- if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) -+ if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0) - goto nla_put_failure; - - if (fi->fib_prefsrc && -diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c -index 7c52afb98c42..5c598f99a500 100644 ---- a/net/ipv4/fib_trie.c -+++ b/net/ipv4/fib_trie.c -@@ -1906,6 +1906,8 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, - - /* rcu_read_lock is hold by caller */ - hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { -+ int err; -+ - if (i < s_i) { - i++; - continue; -@@ -1916,17 +1918,14 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, - continue; - } - -- if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid, -- cb->nlh->nlmsg_seq, -- RTM_NEWROUTE, -- tb->tb_id, -- fa->fa_type, -- xkey, -- KEYLENGTH - fa->fa_slen, -- fa->fa_tos, -- fa->fa_info, NLM_F_MULTI) < 0) { -+ err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid, -+ cb->nlh->nlmsg_seq, RTM_NEWROUTE, -+ tb->tb_id, fa->fa_type, -+ xkey, KEYLENGTH - fa->fa_slen, -+ fa->fa_tos, fa->fa_info, NLM_F_MULTI); -+ if (err < 0) { - cb->args[4] = i; -- return -1; -+ return err; - } - i++; - } -@@ -1948,10 +1947,13 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, - t_key key = cb->args[3]; - - while ((l = leaf_walk_rcu(&tp, key)) != NULL) { -- if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) { -+ int err; -+ -+ err = fn_trie_dump_leaf(l, tb, skb, cb); -+ if (err < 0) { - cb->args[3] = key; - cb->args[2] = count; -- return -1; -+ return err; - } - - ++count; -diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c -index 64148914803a..45fa2aaa3d3f 100644 ---- a/net/ipv4/inet_connection_sock.c -+++ b/net/ipv4/inet_connection_sock.c -@@ -669,6 +669,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk, - inet_sk(newsk)->inet_sport = htons(inet_rsk(req)->ir_num); - newsk->sk_write_space = sk_stream_write_space; - -+ inet_sk(newsk)->mc_list = NULL; -+ - newsk->sk_mark = inet_rsk(req)->ir_mark; - atomic64_set(&newsk->sk_cookie, - atomic64_read(&inet_rsk(req)->ir_cookie)); -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index 375248b900ba..c295d882c6e0 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -1356,8 +1356,12 @@ static void rt_add_uncached_list(struct rtable *rt) - - static void ipv4_dst_destroy(struct dst_entry *dst) - { -+ struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); - struct rtable *rt = (struct rtable *) dst; - -+ if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt)) -+ kfree(p); -+ - if (!list_empty(&rt->rt_uncached)) { - struct uncached_list *ul = rt->rt_uncached_list; - -@@ -1409,7 +1413,11 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr, - rt->rt_gateway = nh->nh_gw; - rt->rt_uses_gateway = 1; - } -- dst_init_metrics(&rt->dst, fi->fib_metrics, true); -+ dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true); -+ if (fi->fib_metrics != &dst_default_metrics) { -+ rt->dst._metrics |= DST_METRICS_REFCOUNTED; -+ atomic_inc(&fi->fib_metrics->refcnt); -+ } - #ifdef CONFIG_IP_ROUTE_CLASSID - rt->dst.tclassid = nh->nh_tclassid; - #endif -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index e1d51370977b..4bd8678329d6 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -1071,9 +1071,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, - int *copied, size_t size) - { - struct tcp_sock *tp = tcp_sk(sk); -+ struct sockaddr *uaddr = msg->msg_name; - int err, flags; - -- if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE)) -+ if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) || -+ (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) && -+ uaddr->sa_family == AF_UNSPEC)) - return -EOPNOTSUPP; - if (tp->fastopen_req) - return -EALREADY; /* Another Fast Open is in progress */ -@@ -1086,7 +1089,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, - tp->fastopen_req->size = size; - - flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0; -- err = __inet_stream_connect(sk->sk_socket, msg->msg_name, -+ err = __inet_stream_connect(sk->sk_socket, uaddr, - msg->msg_namelen, flags); - *copied = tp->fastopen_req->copied; - tcp_free_fastopen_req(tp); -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 818630cec54f..87791f803627 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -1134,13 +1134,14 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, - */ - if (pkt_len > mss) { - unsigned int new_len = (pkt_len / mss) * mss; -- if (!in_sack && new_len < pkt_len) { -+ if (!in_sack && new_len < pkt_len) - new_len += mss; -- if (new_len >= skb->len) -- return 0; -- } - pkt_len = new_len; - } -+ -+ if (pkt_len >= skb->len && !in_sack) -+ return 0; -+ - err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC); - if (err < 0) - return err; -@@ -3219,7 +3220,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, - int delta; - - /* Non-retransmitted hole got filled? That's reordering */ -- if (reord < prior_fackets) -+ if (reord < prior_fackets && reord <= tp->fackets_out) - tcp_update_reordering(sk, tp->fackets_out - reord, 0); - - delta = tcp_is_fack(tp) ? pkts_acked : -diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c -index 225f5f7f26ba..568bc0a52ca1 100644 ---- a/net/ipv6/ip6_offload.c -+++ b/net/ipv6/ip6_offload.c -@@ -62,7 +62,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, - const struct net_offload *ops; - int proto; - struct frag_hdr *fptr; -- unsigned int unfrag_ip6hlen; - u8 *prevhdr; - int offset = 0; - bool encap, udpfrag; -@@ -121,8 +120,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, - skb->network_header = (u8 *)ipv6h - skb->head; - - if (udpfrag) { -- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); -- fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); -+ int err = ip6_find_1stfragopt(skb, &prevhdr); -+ if (err < 0) -+ return ERR_PTR(err); -+ fptr = (struct frag_hdr *)((u8 *)ipv6h + err); - fptr->frag_off = htons(offset); - if (skb->next) - fptr->frag_off |= htons(IP6_MF); -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 8004532fa882..1db17efe36c1 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -571,7 +571,10 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, - int ptr, offset = 0, err = 0; - u8 *prevhdr, nexthdr = 0; - -- hlen = ip6_find_1stfragopt(skb, &prevhdr); -+ err = ip6_find_1stfragopt(skb, &prevhdr); -+ if (err < 0) -+ goto fail; -+ hlen = err; - nexthdr = *prevhdr; - - mtu = ip6_skb_dst_mtu(skb); -@@ -1429,6 +1432,11 @@ alloc_new_skb: - */ - alloclen += sizeof(struct frag_hdr); - -+ copy = datalen - transhdrlen - fraggap; -+ if (copy < 0) { -+ err = -EINVAL; -+ goto error; -+ } - if (transhdrlen) { - skb = sock_alloc_send_skb(sk, - alloclen + hh_len, -@@ -1478,13 +1486,9 @@ alloc_new_skb: - data += fraggap; - pskb_trim_unique(skb_prev, maxfraglen); - } -- copy = datalen - transhdrlen - fraggap; -- -- if (copy < 0) { -- err = -EINVAL; -- kfree_skb(skb); -- goto error; -- } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { -+ if (copy > 0 && -+ getfrag(from, data + transhdrlen, offset, -+ copy, fraggap, skb) < 0) { - err = -EFAULT; - kfree_skb(skb); - goto error; -diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c -index 1d184322a7b1..8b56c5240429 100644 ---- a/net/ipv6/output_core.c -+++ b/net/ipv6/output_core.c -@@ -79,14 +79,13 @@ EXPORT_SYMBOL(ipv6_select_ident); - int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - { - u16 offset = sizeof(struct ipv6hdr); -- struct ipv6_opt_hdr *exthdr = -- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); - unsigned int packet_len = skb_tail_pointer(skb) - - skb_network_header(skb); - int found_rhdr = 0; - *nexthdr = &ipv6_hdr(skb)->nexthdr; - -- while (offset + 1 <= packet_len) { -+ while (offset <= packet_len) { -+ struct ipv6_opt_hdr *exthdr; - - switch (**nexthdr) { - -@@ -107,13 +106,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - return offset; - } - -- offset += ipv6_optlen(exthdr); -- *nexthdr = &exthdr->nexthdr; -+ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len) -+ return -EINVAL; -+ - exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + - offset); -+ offset += ipv6_optlen(exthdr); -+ *nexthdr = &exthdr->nexthdr; - } - -- return offset; -+ return -EINVAL; - } - EXPORT_SYMBOL(ip6_find_1stfragopt); - -diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c -index 1a63c4deef26..8e958fde6e4b 100644 ---- a/net/ipv6/tcp_ipv6.c -+++ b/net/ipv6/tcp_ipv6.c -@@ -1033,6 +1033,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * - newtp->af_specific = &tcp_sock_ipv6_mapped_specific; - #endif - -+ newnp->ipv6_mc_list = NULL; - newnp->ipv6_ac_list = NULL; - newnp->ipv6_fl_list = NULL; - newnp->pktoptions = NULL; -@@ -1102,6 +1103,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * - First: no IPv4 options. - */ - newinet->inet_opt = NULL; -+ newnp->ipv6_mc_list = NULL; - newnp->ipv6_ac_list = NULL; - newnp->ipv6_fl_list = NULL; - -diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c -index 7441e1e63893..01582966ffa0 100644 ---- a/net/ipv6/udp_offload.c -+++ b/net/ipv6/udp_offload.c -@@ -29,6 +29,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, - u8 frag_hdr_sz = sizeof(struct frag_hdr); - __wsum csum; - int tnl_hlen; -+ int err; - - mss = skb_shinfo(skb)->gso_size; - if (unlikely(skb->len <= mss)) -@@ -97,7 +98,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, - /* Find the unfragmentable header and shift it left by frag_hdr_sz - * bytes to insert fragment header. - */ -- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); -+ err = ip6_find_1stfragopt(skb, &prevhdr); -+ if (err < 0) -+ return ERR_PTR(err); -+ unfrag_ip6hlen = err; - nexthdr = *prevhdr; - *prevhdr = NEXTHDR_FRAGMENT; - unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) + -diff --git a/net/sctp/input.c b/net/sctp/input.c -index b6493b3f11a9..2d7859c03fd2 100644 ---- a/net/sctp/input.c -+++ b/net/sctp/input.c -@@ -472,15 +472,14 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, - struct sctp_association **app, - struct sctp_transport **tpp) - { -+ struct sctp_init_chunk *chunkhdr, _chunkhdr; - union sctp_addr saddr; - union sctp_addr daddr; - struct sctp_af *af; - struct sock *sk = NULL; - struct sctp_association *asoc; - struct sctp_transport *transport = NULL; -- struct sctp_init_chunk *chunkhdr; - __u32 vtag = ntohl(sctphdr->vtag); -- int len = skb->len - ((void *)sctphdr - (void *)skb->data); - - *app = NULL; *tpp = NULL; - -@@ -515,13 +514,16 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, - * discard the packet. - */ - if (vtag == 0) { -- chunkhdr = (void *)sctphdr + sizeof(struct sctphdr); -- if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) -- + sizeof(__be32) || -+ /* chunk header + first 4 octects of init header */ -+ chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) + -+ sizeof(struct sctphdr), -+ sizeof(struct sctp_chunkhdr) + -+ sizeof(__be32), &_chunkhdr); -+ if (!chunkhdr || - chunkhdr->chunk_hdr.type != SCTP_CID_INIT || -- ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { -+ ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) - goto out; -- } -+ - } else if (vtag != asoc->c.peer_vtag) { - goto out; - } -diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c -index ce46f1c7f133..7527c168e471 100644 ---- a/net/sctp/ipv6.c -+++ b/net/sctp/ipv6.c -@@ -239,12 +239,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - struct sctp_bind_addr *bp; - struct ipv6_pinfo *np = inet6_sk(sk); - struct sctp_sockaddr_entry *laddr; -- union sctp_addr *baddr = NULL; - union sctp_addr *daddr = &t->ipaddr; - union sctp_addr dst_saddr; - struct in6_addr *final_p, final; - __u8 matchlen = 0; -- __u8 bmatchlen; - sctp_scope_t scope; - - memset(fl6, 0, sizeof(struct flowi6)); -@@ -311,23 +309,37 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, - */ - rcu_read_lock(); - list_for_each_entry_rcu(laddr, &bp->address_list, list) { -- if (!laddr->valid) -+ struct dst_entry *bdst; -+ __u8 bmatchlen; -+ -+ if (!laddr->valid || -+ laddr->state != SCTP_ADDR_SRC || -+ laddr->a.sa.sa_family != AF_INET6 || -+ scope > sctp_scope(&laddr->a)) - continue; -- if ((laddr->state == SCTP_ADDR_SRC) && -- (laddr->a.sa.sa_family == AF_INET6) && -- (scope <= sctp_scope(&laddr->a))) { -- bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); -- if (!baddr || (matchlen < bmatchlen)) { -- baddr = &laddr->a; -- matchlen = bmatchlen; -- } -- } -- } -- if (baddr) { -- fl6->saddr = baddr->v6.sin6_addr; -- fl6->fl6_sport = baddr->v6.sin6_port; -+ -+ fl6->saddr = laddr->a.v6.sin6_addr; -+ fl6->fl6_sport = laddr->a.v6.sin6_port; - final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); -- dst = ip6_dst_lookup_flow(sk, fl6, final_p); -+ bdst = ip6_dst_lookup_flow(sk, fl6, final_p); -+ -+ if (!IS_ERR(bdst) && -+ ipv6_chk_addr(dev_net(bdst->dev), -+ &laddr->a.v6.sin6_addr, bdst->dev, 1)) { -+ if (!IS_ERR_OR_NULL(dst)) -+ dst_release(dst); -+ dst = bdst; -+ break; -+ } -+ -+ bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); -+ if (matchlen > bmatchlen) -+ continue; -+ -+ if (!IS_ERR_OR_NULL(dst)) -+ dst_release(dst); -+ dst = bdst; -+ matchlen = bmatchlen; - } - rcu_read_unlock(); - -@@ -662,6 +674,9 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, - newnp = inet6_sk(newsk); - - memcpy(newnp, np, sizeof(struct ipv6_pinfo)); -+ newnp->ipv6_mc_list = NULL; -+ newnp->ipv6_ac_list = NULL; -+ newnp->ipv6_fl_list = NULL; - - rcu_read_lock(); - opt = rcu_dereference(np->opt); -diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c -index 37b70f8e878f..0abab7926dca 100644 ---- a/sound/pci/hda/patch_sigmatel.c -+++ b/sound/pci/hda/patch_sigmatel.c -@@ -1537,6 +1537,8 @@ static const struct snd_pci_quirk stac9200_fixup_tbl[] = { - "Dell Inspiron 1501", STAC_9200_DELL_M26), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, - "unknown Dell", STAC_9200_DELL_M26), -+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201, -+ "Dell Latitude D430", STAC_9200_DELL_M22), - /* Panasonic */ - SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), - /* Gateway machines needs EAPD to be set on resume */ diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.71-72.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.71-72.patch deleted file mode 100644 index db3b356ad..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.71-72.patch +++ /dev/null @@ -1,3348 +0,0 @@ -diff --git a/Makefile b/Makefile -index ad91a79aed51..94d663c935c0 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 71 -+SUBLEVEL = 72 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S -index 3988e72d16ff..bfc5aae0c280 100644 ---- a/arch/arm/kvm/init.S -+++ b/arch/arm/kvm/init.S -@@ -110,7 +110,6 @@ __do_hyp_init: - @ - Write permission implies XN: disabled - @ - Instruction cache: enabled - @ - Data/Unified cache: enabled -- @ - Memory alignment checks: enabled - @ - MMU: enabled (this code must be run from an identity mapping) - mrc p15, 4, r0, c1, c0, 0 @ HSCR - ldr r2, =HSCTLR_MASK -@@ -118,8 +117,8 @@ __do_hyp_init: - mrc p15, 0, r1, c1, c0, 0 @ SCTLR - ldr r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C) - and r1, r1, r2 -- ARM( ldr r2, =(HSCTLR_M | HSCTLR_A) ) -- THUMB( ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE) ) -+ ARM( ldr r2, =(HSCTLR_M) ) -+ THUMB( ldr r2, =(HSCTLR_M | HSCTLR_TE) ) - orr r1, r1, r2 - orr r0, r0, r1 - isb -diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c -index 01cf10556081..1f1ff7e7b9cf 100644 ---- a/arch/arm/kvm/mmu.c -+++ b/arch/arm/kvm/mmu.c -@@ -869,6 +869,9 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache - pmd_t *pmd; - - pud = stage2_get_pud(kvm, cache, addr); -+ if (!pud) -+ return NULL; -+ - if (pud_none(*pud)) { - if (!cache) - return NULL; -diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h -new file mode 100644 -index 000000000000..be2d2347d995 ---- /dev/null -+++ b/arch/arm64/include/asm/asm-uaccess.h -@@ -0,0 +1,13 @@ -+#ifndef __ASM_ASM_UACCESS_H -+#define __ASM_ASM_UACCESS_H -+ -+/* -+ * Remove the address tag from a virtual address, if present. -+ */ -+ .macro clear_address_tag, dst, addr -+ tst \addr, #(1 << 55) -+ bic \dst, \addr, #(0xff << 56) -+ csel \dst, \dst, \addr, eq -+ .endm -+ -+#endif -diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h -index 9622eb48f894..f2d2c0bbe21b 100644 ---- a/arch/arm64/include/asm/barrier.h -+++ b/arch/arm64/include/asm/barrier.h -@@ -41,23 +41,33 @@ - - #define smp_store_release(p, v) \ - do { \ -+ union { typeof(*p) __val; char __c[1]; } __u = \ -+ { .__val = (__force typeof(*p)) (v) }; \ - compiletime_assert_atomic_type(*p); \ - switch (sizeof(*p)) { \ - case 1: \ - asm volatile ("stlrb %w1, %0" \ -- : "=Q" (*p) : "r" (v) : "memory"); \ -+ : "=Q" (*p) \ -+ : "r" (*(__u8 *)__u.__c) \ -+ : "memory"); \ - break; \ - case 2: \ - asm volatile ("stlrh %w1, %0" \ -- : "=Q" (*p) : "r" (v) : "memory"); \ -+ : "=Q" (*p) \ -+ : "r" (*(__u16 *)__u.__c) \ -+ : "memory"); \ - break; \ - case 4: \ - asm volatile ("stlr %w1, %0" \ -- : "=Q" (*p) : "r" (v) : "memory"); \ -+ : "=Q" (*p) \ -+ : "r" (*(__u32 *)__u.__c) \ -+ : "memory"); \ - break; \ - case 8: \ - asm volatile ("stlr %1, %0" \ -- : "=Q" (*p) : "r" (v) : "memory"); \ -+ : "=Q" (*p) \ -+ : "r" (*(__u64 *)__u.__c) \ -+ : "memory"); \ - break; \ - } \ - } while (0) -diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h -index d9ca1f2c0ea8..829fa6d3e561 100644 ---- a/arch/arm64/include/asm/uaccess.h -+++ b/arch/arm64/include/asm/uaccess.h -@@ -21,6 +21,7 @@ - /* - * User space memory access functions - */ -+#include - #include - #include - -@@ -103,6 +104,13 @@ static inline void set_fs(mm_segment_t fs) - flag; \ - }) - -+/* -+ * When dealing with data aborts, watchpoints, or instruction traps we may end -+ * up with a tagged userland pointer. Clear the tag to get a sane pointer to -+ * pass on to access_ok(), for instance. -+ */ -+#define untagged_addr(addr) sign_extend64(addr, 55) -+ - #define access_ok(type, addr, size) __range_ok(addr, size) - #define user_addr_max get_fs - -diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c -index 937f5e58a4d3..478a00b9732b 100644 ---- a/arch/arm64/kernel/armv8_deprecated.c -+++ b/arch/arm64/kernel/armv8_deprecated.c -@@ -305,7 +305,8 @@ static void register_insn_emulation_sysctl(struct ctl_table *table) - ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \ - CONFIG_ARM64_PAN) \ - : "=&r" (res), "+r" (data), "=&r" (temp) \ -- : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ -+ : "r" ((unsigned long)addr), "i" (-EAGAIN), \ -+ "i" (-EFAULT) \ - : "memory") - - #define __user_swp_asm(data, addr, res, temp) \ -diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S -index bd14849beb73..dccd0c2e9023 100644 ---- a/arch/arm64/kernel/entry.S -+++ b/arch/arm64/kernel/entry.S -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - - /* -@@ -316,12 +317,13 @@ el1_da: - /* - * Data abort handling - */ -- mrs x0, far_el1 -+ mrs x3, far_el1 - enable_dbg - // re-enable interrupts if they were enabled in the aborted context - tbnz x23, #7, 1f // PSR_I_BIT - enable_irq - 1: -+ clear_address_tag x0, x3 - mov x2, sp // struct pt_regs - bl do_mem_abort - -@@ -483,7 +485,7 @@ el0_da: - // enable interrupts before calling the main handler - enable_dbg_and_irq - ct_user_exit -- bic x0, x26, #(0xff << 56) -+ clear_address_tag x0, x26 - mov x1, x25 - mov x2, sp - bl do_mem_abort -diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c -index b45c95d34b83..eeebfc315526 100644 ---- a/arch/arm64/kernel/hw_breakpoint.c -+++ b/arch/arm64/kernel/hw_breakpoint.c -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - - /* Breakpoint currently in use for each BRP. */ - static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); -@@ -690,7 +691,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, - - /* Check if the watchpoint value matches. */ - val = read_wb_reg(AARCH64_DBG_REG_WVR, i); -- if (val != (addr & ~alignment_mask)) -+ if (val != (untagged_addr(addr) & ~alignment_mask)) - goto unlock; - - /* Possible match, check the byte address select to confirm. */ -diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h -index 8b3b46b7b0f2..329771559cbb 100644 ---- a/arch/powerpc/include/asm/topology.h -+++ b/arch/powerpc/include/asm/topology.h -@@ -44,8 +44,22 @@ extern void __init dump_numa_cpu_topology(void); - extern int sysfs_add_device_to_node(struct device *dev, int nid); - extern void sysfs_remove_device_from_node(struct device *dev, int nid); - -+static inline int early_cpu_to_node(int cpu) -+{ -+ int nid; -+ -+ nid = numa_cpu_lookup_table[cpu]; -+ -+ /* -+ * Fall back to node 0 if nid is unset (it should be, except bugs). -+ * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)). -+ */ -+ return (nid < 0) ? 0 : nid; -+} - #else - -+static inline int early_cpu_to_node(int cpu) { return 0; } -+ - static inline void dump_numa_cpu_topology(void) {} - - static inline int sysfs_add_device_to_node(struct device *dev, int nid) -diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c -index c314db8b798c..9837c98caabe 100644 ---- a/arch/powerpc/kernel/eeh_driver.c -+++ b/arch/powerpc/kernel/eeh_driver.c -@@ -655,7 +655,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) - */ - #define MAX_WAIT_FOR_RECOVERY 300 - --static void eeh_handle_normal_event(struct eeh_pe *pe) -+static bool eeh_handle_normal_event(struct eeh_pe *pe) - { - struct pci_bus *frozen_bus; - int rc = 0; -@@ -665,7 +665,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) - if (!frozen_bus) { - pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n", - __func__, pe->phb->global_number, pe->addr); -- return; -+ return false; - } - - eeh_pe_update_time_stamp(pe); -@@ -790,7 +790,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) - pr_info("EEH: Notify device driver to resume\n"); - eeh_pe_dev_traverse(pe, eeh_report_resume, NULL); - -- return; -+ return false; - - excess_failures: - /* -@@ -831,7 +831,11 @@ perm_error: - pci_lock_rescan_remove(); - pcibios_remove_pci_devices(frozen_bus); - pci_unlock_rescan_remove(); -+ -+ /* The passed PE should no longer be used */ -+ return true; - } -+ return false; - } - - static void eeh_handle_special_event(void) -@@ -897,7 +901,14 @@ static void eeh_handle_special_event(void) - */ - if (rc == EEH_NEXT_ERR_FROZEN_PE || - rc == EEH_NEXT_ERR_FENCED_PHB) { -- eeh_handle_normal_event(pe); -+ /* -+ * eeh_handle_normal_event() can make the PE stale if it -+ * determines that the PE cannot possibly be recovered. -+ * Don't modify the PE state if that's the case. -+ */ -+ if (eeh_handle_normal_event(pe)) -+ continue; -+ - eeh_pe_state_clear(pe, EEH_PE_RECOVERING); - } else { - pci_lock_rescan_remove(); -diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c -index a20823210ac0..fe6e800c1357 100644 ---- a/arch/powerpc/kernel/setup_64.c -+++ b/arch/powerpc/kernel/setup_64.c -@@ -751,7 +751,7 @@ void __init setup_arch(char **cmdline_p) - - static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) - { -- return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align, -+ return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align, - __pa(MAX_DMA_ADDRESS)); - } - -@@ -762,7 +762,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size) - - static int pcpu_cpu_distance(unsigned int from, unsigned int to) - { -- if (cpu_to_node(from) == cpu_to_node(to)) -+ if (early_cpu_to_node(from) == early_cpu_to_node(to)) - return LOCAL_DISTANCE; - else - return REMOTE_DISTANCE; -diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c -index e9ff44cd5d86..e8b1027e1b5b 100644 ---- a/arch/powerpc/platforms/pseries/hotplug-memory.c -+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c -@@ -110,6 +110,7 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn) - for (i = 0; i < num_lmbs; i++) { - lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr); - lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index); -+ lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index); - lmbs[i].flags = be32_to_cpu(lmbs[i].flags); - } - -@@ -553,6 +554,7 @@ static void dlpar_update_drconf_property(struct device_node *dn, - for (i = 0; i < num_lmbs; i++) { - lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr); - lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index); -+ lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index); - lmbs[i].flags = cpu_to_be32(lmbs[i].flags); - } - -diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig -index 56442d2d7bbc..eb9487470141 100644 ---- a/arch/sparc/Kconfig -+++ b/arch/sparc/Kconfig -@@ -182,9 +182,9 @@ config NR_CPUS - int "Maximum number of CPUs" - depends on SMP - range 2 32 if SPARC32 -- range 2 1024 if SPARC64 -+ range 2 4096 if SPARC64 - default 32 if SPARC32 -- default 64 if SPARC64 -+ default 4096 if SPARC64 - - source kernel/Kconfig.hz - -diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h -index f7de0dbc38af..83b36a5371ff 100644 ---- a/arch/sparc/include/asm/mmu_64.h -+++ b/arch/sparc/include/asm/mmu_64.h -@@ -52,7 +52,7 @@ - #define CTX_NR_MASK TAG_CONTEXT_BITS - #define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK) - --#define CTX_FIRST_VERSION ((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL)) -+#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT) - #define CTX_VALID(__ctx) \ - (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK)) - #define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK) -diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h -index b84be675e507..349dd23e2876 100644 ---- a/arch/sparc/include/asm/mmu_context_64.h -+++ b/arch/sparc/include/asm/mmu_context_64.h -@@ -17,13 +17,8 @@ extern spinlock_t ctx_alloc_lock; - extern unsigned long tlb_context_cache; - extern unsigned long mmu_context_bmap[]; - -+DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm); - void get_new_mmu_context(struct mm_struct *mm); --#ifdef CONFIG_SMP --void smp_new_mmu_context_version(void); --#else --#define smp_new_mmu_context_version() do { } while (0) --#endif -- - int init_new_context(struct task_struct *tsk, struct mm_struct *mm); - void destroy_context(struct mm_struct *mm); - -@@ -74,8 +69,9 @@ void __flush_tlb_mm(unsigned long, unsigned long); - static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk) - { - unsigned long ctx_valid, flags; -- int cpu; -+ int cpu = smp_processor_id(); - -+ per_cpu(per_cpu_secondary_mm, cpu) = mm; - if (unlikely(mm == &init_mm)) - return; - -@@ -121,7 +117,6 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str - * for the first time, we must flush that context out of the - * local TLB. - */ -- cpu = smp_processor_id(); - if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) { - cpumask_set_cpu(cpu, mm_cpumask(mm)); - __flush_tlb_mm(CTX_HWBITS(mm->context), -@@ -131,26 +126,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str - } - - #define deactivate_mm(tsk,mm) do { } while (0) -- --/* Activate a new MM instance for the current task. */ --static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm) --{ -- unsigned long flags; -- int cpu; -- -- spin_lock_irqsave(&mm->context.lock, flags); -- if (!CTX_VALID(mm->context)) -- get_new_mmu_context(mm); -- cpu = smp_processor_id(); -- if (!cpumask_test_cpu(cpu, mm_cpumask(mm))) -- cpumask_set_cpu(cpu, mm_cpumask(mm)); -- -- load_secondary_context(mm); -- __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT); -- tsb_context_switch(mm); -- spin_unlock_irqrestore(&mm->context.lock, flags); --} -- -+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL) - #endif /* !(__ASSEMBLY__) */ - - #endif /* !(__SPARC64_MMU_CONTEXT_H) */ -diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h -index 266937030546..522b43db2ed3 100644 ---- a/arch/sparc/include/asm/pil.h -+++ b/arch/sparc/include/asm/pil.h -@@ -20,7 +20,6 @@ - #define PIL_SMP_CALL_FUNC 1 - #define PIL_SMP_RECEIVE_SIGNAL 2 - #define PIL_SMP_CAPTURE 3 --#define PIL_SMP_CTX_NEW_VERSION 4 - #define PIL_DEVICE_IRQ 5 - #define PIL_SMP_CALL_FUNC_SNGL 6 - #define PIL_DEFERRED_PCR_WORK 7 -diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h -index 8174f6cdbbbb..9dca7a892978 100644 ---- a/arch/sparc/include/asm/vio.h -+++ b/arch/sparc/include/asm/vio.h -@@ -327,6 +327,7 @@ struct vio_dev { - int compat_len; - - u64 dev_no; -+ u64 id; - - unsigned long channel_id; - -diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c -index e22416ce56ea..bfbde8c4ffb2 100644 ---- a/arch/sparc/kernel/irq_64.c -+++ b/arch/sparc/kernel/irq_64.c -@@ -1034,17 +1034,26 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) - { - #ifdef CONFIG_SMP - unsigned long page; -+ void *mondo, *p; - -- BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); -+ BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > PAGE_SIZE); -+ -+ /* Make sure mondo block is 64byte aligned */ -+ p = kzalloc(127, GFP_KERNEL); -+ if (!p) { -+ prom_printf("SUN4V: Error, cannot allocate mondo block.\n"); -+ prom_halt(); -+ } -+ mondo = (void *)(((unsigned long)p + 63) & ~0x3f); -+ tb->cpu_mondo_block_pa = __pa(mondo); - - page = get_zeroed_page(GFP_KERNEL); - if (!page) { -- prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); -+ prom_printf("SUN4V: Error, cannot allocate cpu list page.\n"); - prom_halt(); - } - -- tb->cpu_mondo_block_pa = __pa(page); -- tb->cpu_list_pa = __pa(page + 64); -+ tb->cpu_list_pa = __pa(page); - #endif - } - -diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h -index e7f652be9e61..44f32dd4477f 100644 ---- a/arch/sparc/kernel/kernel.h -+++ b/arch/sparc/kernel/kernel.h -@@ -37,7 +37,6 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr - /* smp_64.c */ - void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs); - void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs); --void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs); - void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs); - void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs); - -diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c -index 19cd08d18672..95a9fa0d2195 100644 ---- a/arch/sparc/kernel/smp_64.c -+++ b/arch/sparc/kernel/smp_64.c -@@ -959,37 +959,6 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) - preempt_enable(); - } - --void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) --{ -- struct mm_struct *mm; -- unsigned long flags; -- -- clear_softint(1 << irq); -- -- /* See if we need to allocate a new TLB context because -- * the version of the one we are using is now out of date. -- */ -- mm = current->active_mm; -- if (unlikely(!mm || (mm == &init_mm))) -- return; -- -- spin_lock_irqsave(&mm->context.lock, flags); -- -- if (unlikely(!CTX_VALID(mm->context))) -- get_new_mmu_context(mm); -- -- spin_unlock_irqrestore(&mm->context.lock, flags); -- -- load_secondary_context(mm); -- __flush_tlb_mm(CTX_HWBITS(mm->context), -- SECONDARY_CONTEXT); --} -- --void smp_new_mmu_context_version(void) --{ -- smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0); --} -- - #ifdef CONFIG_KGDB - void kgdb_roundup_cpus(unsigned long flags) - { -diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S -index d568c8207af7..395ec1800530 100644 ---- a/arch/sparc/kernel/tsb.S -+++ b/arch/sparc/kernel/tsb.S -@@ -470,13 +470,16 @@ __tsb_context_switch: - .type copy_tsb,#function - copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size - * %o2=new_tsb_base, %o3=new_tsb_size -+ * %o4=page_size_shift - */ - sethi %uhi(TSB_PASS_BITS), %g7 - srlx %o3, 4, %o3 -- add %o0, %o1, %g1 /* end of old tsb */ -+ add %o0, %o1, %o1 /* end of old tsb */ - sllx %g7, 32, %g7 - sub %o3, 1, %o3 /* %o3 == new tsb hash mask */ - -+ mov %o4, %g1 /* page_size_shift */ -+ - 661: prefetcha [%o0] ASI_N, #one_read - .section .tsb_phys_patch, "ax" - .word 661b -@@ -501,9 +504,9 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size - /* This can definitely be computed faster... */ - srlx %o0, 4, %o5 /* Build index */ - and %o5, 511, %o5 /* Mask index */ -- sllx %o5, PAGE_SHIFT, %o5 /* Put into vaddr position */ -+ sllx %o5, %g1, %o5 /* Put into vaddr position */ - or %o4, %o5, %o4 /* Full VADDR. */ -- srlx %o4, PAGE_SHIFT, %o4 /* Shift down to create index */ -+ srlx %o4, %g1, %o4 /* Shift down to create index */ - and %o4, %o3, %o4 /* Mask with new_tsb_nents-1 */ - sllx %o4, 4, %o4 /* Shift back up into tsb ent offset */ - TSB_STORE(%o2 + %o4, %g2) /* Store TAG */ -@@ -511,7 +514,7 @@ copy_tsb: /* %o0=old_tsb_base, %o1=old_tsb_size - TSB_STORE(%o2 + %o4, %g3) /* Store TTE */ - - 80: add %o0, 16, %o0 -- cmp %o0, %g1 -+ cmp %o0, %o1 - bne,pt %xcc, 90b - nop - -diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S -index c6dfdaa29e20..170ead662f2a 100644 ---- a/arch/sparc/kernel/ttable_64.S -+++ b/arch/sparc/kernel/ttable_64.S -@@ -50,7 +50,7 @@ tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40) - tl0_irq1: TRAP_IRQ(smp_call_function_client, 1) - tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2) - tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3) --tl0_irq4: TRAP_IRQ(smp_new_mmu_context_version_client, 4) -+tl0_irq4: BTRAP(0x44) - #else - tl0_irq1: BTRAP(0x41) - tl0_irq2: BTRAP(0x42) -diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c -index cb5789c9f961..34824ca396f0 100644 ---- a/arch/sparc/kernel/vio.c -+++ b/arch/sparc/kernel/vio.c -@@ -284,13 +284,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, - if (!id) { - dev_set_name(&vdev->dev, "%s", bus_id_name); - vdev->dev_no = ~(u64)0; -+ vdev->id = ~(u64)0; - } else if (!cfg_handle) { - dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id); - vdev->dev_no = *id; -+ vdev->id = ~(u64)0; - } else { - dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name, - *cfg_handle, *id); - vdev->dev_no = *cfg_handle; -+ vdev->id = *id; - } - - vdev->dev.parent = parent; -@@ -333,27 +336,84 @@ static void vio_add(struct mdesc_handle *hp, u64 node) - (void) vio_create_one(hp, node, &root_vdev->dev); - } - -+struct vio_md_node_query { -+ const char *type; -+ u64 dev_no; -+ u64 id; -+}; -+ - static int vio_md_node_match(struct device *dev, void *arg) - { -+ struct vio_md_node_query *query = (struct vio_md_node_query *) arg; - struct vio_dev *vdev = to_vio_dev(dev); - -- if (vdev->mp == (u64) arg) -- return 1; -+ if (vdev->dev_no != query->dev_no) -+ return 0; -+ if (vdev->id != query->id) -+ return 0; -+ if (strcmp(vdev->type, query->type)) -+ return 0; - -- return 0; -+ return 1; - } - - static void vio_remove(struct mdesc_handle *hp, u64 node) - { -+ const char *type; -+ const u64 *id, *cfg_handle; -+ u64 a; -+ struct vio_md_node_query query; - struct device *dev; - -- dev = device_find_child(&root_vdev->dev, (void *) node, -+ type = mdesc_get_property(hp, node, "device-type", NULL); -+ if (!type) { -+ type = mdesc_get_property(hp, node, "name", NULL); -+ if (!type) -+ type = mdesc_node_name(hp, node); -+ } -+ -+ query.type = type; -+ -+ id = mdesc_get_property(hp, node, "id", NULL); -+ cfg_handle = NULL; -+ mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) { -+ u64 target; -+ -+ target = mdesc_arc_target(hp, a); -+ cfg_handle = mdesc_get_property(hp, target, -+ "cfg-handle", NULL); -+ if (cfg_handle) -+ break; -+ } -+ -+ if (!id) { -+ query.dev_no = ~(u64)0; -+ query.id = ~(u64)0; -+ } else if (!cfg_handle) { -+ query.dev_no = *id; -+ query.id = ~(u64)0; -+ } else { -+ query.dev_no = *cfg_handle; -+ query.id = *id; -+ } -+ -+ dev = device_find_child(&root_vdev->dev, &query, - vio_md_node_match); - if (dev) { - printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev)); - - device_unregister(dev); - put_device(dev); -+ } else { -+ if (!id) -+ printk(KERN_ERR "VIO: Removed unknown %s node.\n", -+ type); -+ else if (!cfg_handle) -+ printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n", -+ type, *id); -+ else -+ printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n", -+ type, *cfg_handle, *id); - } - } - -diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c -index 965655afdbb6..384aba109d7c 100644 ---- a/arch/sparc/mm/init_64.c -+++ b/arch/sparc/mm/init_64.c -@@ -656,10 +656,58 @@ EXPORT_SYMBOL(__flush_dcache_range); - - /* get_new_mmu_context() uses "cache + 1". */ - DEFINE_SPINLOCK(ctx_alloc_lock); --unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; -+unsigned long tlb_context_cache = CTX_FIRST_VERSION; - #define MAX_CTX_NR (1UL << CTX_NR_BITS) - #define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR) - DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR); -+DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0}; -+ -+static void mmu_context_wrap(void) -+{ -+ unsigned long old_ver = tlb_context_cache & CTX_VERSION_MASK; -+ unsigned long new_ver, new_ctx, old_ctx; -+ struct mm_struct *mm; -+ int cpu; -+ -+ bitmap_zero(mmu_context_bmap, 1 << CTX_NR_BITS); -+ -+ /* Reserve kernel context */ -+ set_bit(0, mmu_context_bmap); -+ -+ new_ver = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION; -+ if (unlikely(new_ver == 0)) -+ new_ver = CTX_FIRST_VERSION; -+ tlb_context_cache = new_ver; -+ -+ /* -+ * Make sure that any new mm that are added into per_cpu_secondary_mm, -+ * are going to go through get_new_mmu_context() path. -+ */ -+ mb(); -+ -+ /* -+ * Updated versions to current on those CPUs that had valid secondary -+ * contexts -+ */ -+ for_each_online_cpu(cpu) { -+ /* -+ * If a new mm is stored after we took this mm from the array, -+ * it will go into get_new_mmu_context() path, because we -+ * already bumped the version in tlb_context_cache. -+ */ -+ mm = per_cpu(per_cpu_secondary_mm, cpu); -+ -+ if (unlikely(!mm || mm == &init_mm)) -+ continue; -+ -+ old_ctx = mm->context.sparc64_ctx_val; -+ if (likely((old_ctx & CTX_VERSION_MASK) == old_ver)) { -+ new_ctx = (old_ctx & ~CTX_VERSION_MASK) | new_ver; -+ set_bit(new_ctx & CTX_NR_MASK, mmu_context_bmap); -+ mm->context.sparc64_ctx_val = new_ctx; -+ } -+ } -+} - - /* Caller does TLB context flushing on local CPU if necessary. - * The caller also ensures that CTX_VALID(mm->context) is false. -@@ -675,48 +723,30 @@ void get_new_mmu_context(struct mm_struct *mm) - { - unsigned long ctx, new_ctx; - unsigned long orig_pgsz_bits; -- int new_version; - - spin_lock(&ctx_alloc_lock); -+retry: -+ /* wrap might have happened, test again if our context became valid */ -+ if (unlikely(CTX_VALID(mm->context))) -+ goto out; - orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK); - ctx = (tlb_context_cache + 1) & CTX_NR_MASK; - new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx); -- new_version = 0; - if (new_ctx >= (1 << CTX_NR_BITS)) { - new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1); - if (new_ctx >= ctx) { -- int i; -- new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + -- CTX_FIRST_VERSION; -- if (new_ctx == 1) -- new_ctx = CTX_FIRST_VERSION; -- -- /* Don't call memset, for 16 entries that's just -- * plain silly... -- */ -- mmu_context_bmap[0] = 3; -- mmu_context_bmap[1] = 0; -- mmu_context_bmap[2] = 0; -- mmu_context_bmap[3] = 0; -- for (i = 4; i < CTX_BMAP_SLOTS; i += 4) { -- mmu_context_bmap[i + 0] = 0; -- mmu_context_bmap[i + 1] = 0; -- mmu_context_bmap[i + 2] = 0; -- mmu_context_bmap[i + 3] = 0; -- } -- new_version = 1; -- goto out; -+ mmu_context_wrap(); -+ goto retry; - } - } -+ if (mm->context.sparc64_ctx_val) -+ cpumask_clear(mm_cpumask(mm)); - mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63)); - new_ctx |= (tlb_context_cache & CTX_VERSION_MASK); --out: - tlb_context_cache = new_ctx; - mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits; -+out: - spin_unlock(&ctx_alloc_lock); -- -- if (unlikely(new_version)) -- smp_new_mmu_context_version(); - } - - static int numa_enabled = 1; -diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c -index 9cdeca0fa955..266411291634 100644 ---- a/arch/sparc/mm/tsb.c -+++ b/arch/sparc/mm/tsb.c -@@ -451,7 +451,8 @@ retry_tsb_alloc: - extern void copy_tsb(unsigned long old_tsb_base, - unsigned long old_tsb_size, - unsigned long new_tsb_base, -- unsigned long new_tsb_size); -+ unsigned long new_tsb_size, -+ unsigned long page_size_shift); - unsigned long old_tsb_base = (unsigned long) old_tsb; - unsigned long new_tsb_base = (unsigned long) new_tsb; - -@@ -459,7 +460,9 @@ retry_tsb_alloc: - old_tsb_base = __pa(old_tsb_base); - new_tsb_base = __pa(new_tsb_base); - } -- copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size); -+ copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size, -+ tsb_index == MM_TSB_BASE ? -+ PAGE_SHIFT : REAL_HPAGE_SHIFT); - } - - mm->context.tsb_block[tsb_index].tsb = new_tsb; -diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S -index 5d2fd6cd3189..fcf4d27a38fb 100644 ---- a/arch/sparc/mm/ultra.S -+++ b/arch/sparc/mm/ultra.S -@@ -971,11 +971,6 @@ xcall_capture: - wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint - retry - -- .globl xcall_new_mmu_context_version --xcall_new_mmu_context_version: -- wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint -- retry -- - #ifdef CONFIG_KGDB - .globl xcall_kgdb_capture - xcall_kgdb_capture: -diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c -index 47190bd399e7..cec49ecf5f31 100644 ---- a/arch/x86/kernel/kvm.c -+++ b/arch/x86/kernel/kvm.c -@@ -161,8 +161,8 @@ void kvm_async_pf_task_wait(u32 token) - */ - rcu_irq_exit(); - native_safe_halt(); -- rcu_irq_enter(); - local_irq_disable(); -+ rcu_irq_enter(); - } - } - if (!n.halted) -diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c -index 642e9c93a097..9357b29de9bc 100644 ---- a/arch/x86/kvm/cpuid.c -+++ b/arch/x86/kvm/cpuid.c -@@ -737,18 +737,20 @@ out: - static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i) - { - struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i]; -- int j, nent = vcpu->arch.cpuid_nent; -+ struct kvm_cpuid_entry2 *ej; -+ int j = i; -+ int nent = vcpu->arch.cpuid_nent; - - e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT; - /* when no next entry is found, the current entry[i] is reselected */ -- for (j = i + 1; ; j = (j + 1) % nent) { -- struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j]; -- if (ej->function == e->function) { -- ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; -- return j; -- } -- } -- return 0; /* silence gcc, even though control never reaches here */ -+ do { -+ j = (j + 1) % nent; -+ ej = &vcpu->arch.cpuid_entries[j]; -+ } while (ej->function != e->function); -+ -+ ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; -+ -+ return j; - } - - /* find an entry with matching function, matching index (if needed), and that -diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c -index 8eb8a934b531..1049c3c9b877 100644 ---- a/arch/x86/kvm/mmu.c -+++ b/arch/x86/kvm/mmu.c -@@ -3433,12 +3433,15 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn) - return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch); - } - --static bool can_do_async_pf(struct kvm_vcpu *vcpu) -+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu) - { - if (unlikely(!lapic_in_kernel(vcpu) || - kvm_event_needs_reinjection(vcpu))) - return false; - -+ if (is_guest_mode(vcpu)) -+ return false; -+ - return kvm_x86_ops->interrupt_allowed(vcpu); - } - -@@ -3454,7 +3457,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, - if (!async) - return false; /* *pfn has correct page already */ - -- if (!prefault && can_do_async_pf(vcpu)) { -+ if (!prefault && kvm_can_do_async_pf(vcpu)) { - trace_kvm_try_async_get_page(gva, gfn); - if (kvm_find_async_pf_gfn(vcpu, gfn)) { - trace_kvm_async_pf_doublefault(gva, gfn); -diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h -index 55ffb7b0f95e..e60fc80f8a9c 100644 ---- a/arch/x86/kvm/mmu.h -+++ b/arch/x86/kvm/mmu.h -@@ -74,6 +74,7 @@ enum { - int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct); - void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu); - void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly); -+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu); - - static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm) - { -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index ae2b9cd358f2..6c82792487e9 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -8245,8 +8245,7 @@ bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) - if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED)) - return true; - else -- return !kvm_event_needs_reinjection(vcpu) && -- kvm_x86_ops->interrupt_allowed(vcpu); -+ return kvm_can_do_async_pf(vcpu); - } - - void kvm_arch_start_assignment(struct kvm *kvm) -diff --git a/crypto/gcm.c b/crypto/gcm.c -index 1238b3c5a321..0a12c09d7cb2 100644 ---- a/crypto/gcm.c -+++ b/crypto/gcm.c -@@ -152,10 +152,8 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, - - err = crypto_ablkcipher_encrypt(&data->req); - if (err == -EINPROGRESS || err == -EBUSY) { -- err = wait_for_completion_interruptible( -- &data->result.completion); -- if (!err) -- err = data->result.err; -+ wait_for_completion(&data->result.completion); -+ err = data->result.err; - } - - if (err) -diff --git a/drivers/char/mem.c b/drivers/char/mem.c -index 0975d23031ea..2898d19fadf5 100644 ---- a/drivers/char/mem.c -+++ b/drivers/char/mem.c -@@ -346,7 +346,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) - phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; - - /* It's illegal to wrap around the end of the physical address space. */ -- if (offset + (phys_addr_t)size < offset) -+ if (offset + (phys_addr_t)size - 1 < offset) - return -EINVAL; - - if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) -diff --git a/drivers/char/random.c b/drivers/char/random.c -index 491a4dce13fe..1822472dffab 100644 ---- a/drivers/char/random.c -+++ b/drivers/char/random.c -@@ -1798,13 +1798,15 @@ int random_int_secret_init(void) - return 0; - } - -+static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash) -+ __aligned(sizeof(unsigned long)); -+ - /* - * Get a random word for internal kernel use only. Similar to urandom but - * with the goal of minimal entropy pool depletion. As a result, the random - * value is not cryptographically secure but for several uses the cost of - * depleting entropy is too high - */ --static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); - unsigned int get_random_int(void) - { - __u32 *hash; -@@ -1825,6 +1827,28 @@ unsigned int get_random_int(void) - EXPORT_SYMBOL(get_random_int); - - /* -+ * Same as get_random_int(), but returns unsigned long. -+ */ -+unsigned long get_random_long(void) -+{ -+ __u32 *hash; -+ unsigned long ret; -+ -+ if (arch_get_random_long(&ret)) -+ return ret; -+ -+ hash = get_cpu_var(get_random_int_hash); -+ -+ hash[0] += current->pid + jiffies + random_get_entropy(); -+ md5_transform(hash, random_int_secret); -+ ret = *(unsigned long *)hash; -+ put_cpu_var(get_random_int_hash); -+ -+ return ret; -+} -+EXPORT_SYMBOL(get_random_long); -+ -+/* - * randomize_range() returns a start address such that - * - * [...... .....] -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index 38b363f4316b..ebed319657e7 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -2451,6 +2451,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) - if (!(cpufreq_driver->flags & CPUFREQ_STICKY) && - list_empty(&cpufreq_policy_list)) { - /* if all ->init() calls failed, unregister */ -+ ret = -ENODEV; - pr_debug("%s: No CPU initialized for driver %s\n", __func__, - driver_data->name); - goto err_if_unreg; -diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c -index 57ff46284f15..c97336a2ba92 100644 ---- a/drivers/dma/ep93xx_dma.c -+++ b/drivers/dma/ep93xx_dma.c -@@ -325,6 +325,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac) - | M2P_CONTROL_ENABLE; - m2p_set_control(edmac, control); - -+ edmac->buffer = 0; -+ - return 0; - } - -diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c -index b1bc945f008f..56410ea75ac5 100644 ---- a/drivers/dma/sh/usb-dmac.c -+++ b/drivers/dma/sh/usb-dmac.c -@@ -117,7 +117,7 @@ struct usb_dmac { - #define USB_DMASWR 0x0008 - #define USB_DMASWR_SWR (1 << 0) - #define USB_DMAOR 0x0060 --#define USB_DMAOR_AE (1 << 2) -+#define USB_DMAOR_AE (1 << 1) - #define USB_DMAOR_DME (1 << 0) - - #define USB_DMASAR 0x0000 -diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c -index 57a2e347f04d..0f0094b58d1f 100644 ---- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c -+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c -@@ -893,6 +893,12 @@ static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev) - u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); - u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300; - -+ /* disable mclk switching if the refresh is >120Hz, even if the -+ * blanking period would allow it -+ */ -+ if (amdgpu_dpm_get_vrefresh(adev) > 120) -+ return true; -+ - if (vblank_time < switch_limit) - return true; - else -diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c -index b88ce514eb8e..24d45fc7716c 100644 ---- a/drivers/gpu/drm/msm/msm_drv.c -+++ b/drivers/gpu/drm/msm/msm_drv.c -@@ -986,6 +986,7 @@ static struct drm_driver msm_driver = { - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, -+ .gem_prime_res_obj = msm_gem_prime_res_obj, - .gem_prime_pin = msm_gem_prime_pin, - .gem_prime_unpin = msm_gem_prime_unpin, - .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, -diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h -index 3be7a56b14f1..026e156e519c 100644 ---- a/drivers/gpu/drm/msm/msm_drv.h -+++ b/drivers/gpu/drm/msm/msm_drv.h -@@ -212,6 +212,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj); - void *msm_gem_prime_vmap(struct drm_gem_object *obj); - void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); - int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); -+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj); - struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, - struct dma_buf_attachment *attach, struct sg_table *sg); - int msm_gem_prime_pin(struct drm_gem_object *obj); -diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c -index 121975b07cd4..1fbddc5c7281 100644 ---- a/drivers/gpu/drm/msm/msm_gem_prime.c -+++ b/drivers/gpu/drm/msm/msm_gem_prime.c -@@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj) - if (!obj->import_attach) - msm_gem_put_pages(obj); - } -+ -+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj) -+{ -+ struct msm_gem_object *msm_obj = to_msm_bo(obj); -+ -+ return msm_obj->resv; -+} -diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h -index 82d3e28918fd..7e4f24ae7de8 100644 ---- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h -+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h -@@ -4,6 +4,7 @@ - - struct nvkm_alarm { - struct list_head head; -+ struct list_head exec; - u64 timestamp; - void (*func)(struct nvkm_alarm *); - }; -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -index 79fcdb43e174..46033909d950 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c -@@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) - /* Move to completed list. We'll drop the lock before - * executing the callback so it can reschedule itself. - */ -- list_move_tail(&alarm->head, &exec); -+ list_del_init(&alarm->head); -+ list_add(&alarm->exec, &exec); - } - - /* Shut down interrupt if no more pending alarms. */ -@@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) - spin_unlock_irqrestore(&tmr->lock, flags); - - /* Execute completed callbacks. */ -- list_for_each_entry_safe(alarm, atemp, &exec, head) { -- list_del_init(&alarm->head); -+ list_for_each_entry_safe(alarm, atemp, &exec, exec) { -+ list_del(&alarm->exec); - alarm->func(alarm); - } - } -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c -index b6a0806b06bf..a1c68e6a689e 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c -@@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv, - return fifo_state->static_buffer; - else { - fifo_state->dynamic_buffer = vmalloc(bytes); -+ if (!fifo_state->dynamic_buffer) -+ goto out_err; - return fifo_state->dynamic_buffer; - } - } -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c -index c9c04ccccdd9..027987023400 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c -@@ -1288,11 +1288,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - int ret; - uint32_t size; -- uint32_t backup_handle; -+ uint32_t backup_handle = 0; - - if (req->multisample_count != 0) - return -EINVAL; - -+ if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS) -+ return -EINVAL; -+ - if (unlikely(vmw_user_surface_size == 0)) - vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + - 128; -@@ -1328,12 +1331,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, - ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle, - &res->backup, - &user_srf->backup_base); -- if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE < -- res->backup_size) { -- DRM_ERROR("Surface backup buffer is too small.\n"); -- vmw_dmabuf_unreference(&res->backup); -- ret = -EINVAL; -- goto out_unlock; -+ if (ret == 0) { -+ if (res->backup->base.num_pages * PAGE_SIZE < -+ res->backup_size) { -+ DRM_ERROR("Surface backup buffer is too small.\n"); -+ vmw_dmabuf_unreference(&res->backup); -+ ret = -EINVAL; -+ goto out_unlock; -+ } else { -+ backup_handle = req->buffer_handle; -+ } - } - } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer) - ret = vmw_user_dmabuf_alloc(dev_priv, tfile, -diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c -index 6bf89d8f3741..b9d1e5c58ec5 100644 ---- a/drivers/iio/light/ltr501.c -+++ b/drivers/iio/light/ltr501.c -@@ -74,9 +74,9 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; - static const struct reg_field reg_field_it = - REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); - static const struct reg_field reg_field_als_intr = -- REG_FIELD(LTR501_INTR, 0, 0); --static const struct reg_field reg_field_ps_intr = - REG_FIELD(LTR501_INTR, 1, 1); -+static const struct reg_field reg_field_ps_intr = -+ REG_FIELD(LTR501_INTR, 0, 0); - static const struct reg_field reg_field_als_rate = - REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2); - static const struct reg_field reg_field_ps_rate = -diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c -index bf0bd7e03aff..9e6d1cdb7fcd 100644 ---- a/drivers/iio/proximity/as3935.c -+++ b/drivers/iio/proximity/as3935.c -@@ -40,9 +40,9 @@ - #define AS3935_AFE_PWR_BIT BIT(0) - - #define AS3935_INT 0x03 --#define AS3935_INT_MASK 0x07 -+#define AS3935_INT_MASK 0x0f - #define AS3935_EVENT_INT BIT(3) --#define AS3935_NOISE_INT BIT(1) -+#define AS3935_NOISE_INT BIT(0) - - #define AS3935_DATA 0x07 - #define AS3935_DATA_MASK 0x3F -diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c -index e6b7556d5221..cbc4216091c9 100644 ---- a/drivers/infiniband/hw/qib/qib_rc.c -+++ b/drivers/infiniband/hw/qib/qib_rc.c -@@ -2088,8 +2088,10 @@ send_last: - ret = qib_get_rwqe(qp, 1); - if (ret < 0) - goto nack_op_err; -- if (!ret) -+ if (!ret) { -+ qib_put_ss(&qp->r_sge); - goto rnr_nak; -+ } - wc.ex.imm_data = ohdr->u.rc.imm_data; - hdrsize += 4; - wc.wc_flags = IB_WC_WITH_IMM; -diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c -index 1a2b2620421e..6f4dc0fd2ca3 100644 ---- a/drivers/input/mouse/elantech.c -+++ b/drivers/input/mouse/elantech.c -@@ -1122,8 +1122,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, - * Asus UX32VD 0x361f02 00, 15, 0e clickpad - * Avatar AVIU-145A2 0x361f00 ? clickpad - * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons -+ * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons - * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons - * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons -+ * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons - * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons - * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) - * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons -@@ -1529,6 +1531,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { - }, - }, - { -+ /* Fujitsu LIFEBOOK E546 does not work with crc_enabled == 0 */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"), -+ }, -+ }, -+ { - /* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -@@ -1550,6 +1559,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { - }, - }, - { -+ /* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"), -+ }, -+ }, -+ { - /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */ - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c -index 783337d22f36..10a02934bfc0 100644 ---- a/drivers/misc/cxl/file.c -+++ b/drivers/misc/cxl/file.c -@@ -158,11 +158,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, - - /* Do this outside the status_mutex to avoid a circular dependency with - * the locking in cxl_mmap_fault() */ -- if (copy_from_user(&work, uwork, -- sizeof(struct cxl_ioctl_start_work))) { -- rc = -EFAULT; -- goto out; -- } -+ if (copy_from_user(&work, uwork, sizeof(work))) -+ return -EFAULT; - - mutex_lock(&ctx->status_mutex); - if (ctx->status != OPENED) { -diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -index c82ab87fcbe8..e5911ccb2148 100644 ---- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c -@@ -1949,7 +1949,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb, - } - - /* select a non-FCoE queue */ -- return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); -+ return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos); - } - - void bnx2x_set_num_queues(struct bnx2x *bp) -diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -index 0d147610a06f..090e00650601 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c -@@ -2714,10 +2714,14 @@ static int cxgb_up(struct adapter *adap) - if (err) - goto irq_err; - } -+ -+ mutex_lock(&uld_mutex); - enable_rx(adap); - t4_sge_start(adap); - t4_intr_enable(adap); - adap->flags |= FULL_INIT_DONE; -+ mutex_unlock(&uld_mutex); -+ - notify_ulds(adap, CXGB4_STATE_UP); - #if IS_ENABLED(CONFIG_IPV6) - update_clip(adap); -diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c -index ff665493ca97..52f2230062e7 100644 ---- a/drivers/net/ethernet/ethoc.c -+++ b/drivers/net/ethernet/ethoc.c -@@ -713,6 +713,8 @@ static int ethoc_open(struct net_device *dev) - if (ret) - return ret; - -+ napi_enable(&priv->napi); -+ - ethoc_init_ring(priv, dev->mem_start); - ethoc_reset(priv); - -@@ -725,7 +727,6 @@ static int ethoc_open(struct net_device *dev) - } - - phy_start(priv->phy); -- napi_enable(&priv->napi); - - if (netif_msg_ifup(priv)) { - dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", -diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c -index 590750ab6564..9a986ccd42e5 100644 ---- a/drivers/net/vxlan.c -+++ b/drivers/net/vxlan.c -@@ -77,6 +77,8 @@ static const u8 all_zeros_mac[ETH_ALEN]; - - static int vxlan_sock_add(struct vxlan_dev *vxlan); - -+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan); -+ - /* per-network namespace private data for this module */ - struct vxlan_net { - struct list_head vxlan_list; -@@ -1052,6 +1054,8 @@ static void __vxlan_sock_release(struct vxlan_sock *vs) - - static void vxlan_sock_release(struct vxlan_dev *vxlan) - { -+ vxlan_vs_del_dev(vxlan); -+ - __vxlan_sock_release(vxlan->vn4_sock); - #if IS_ENABLED(CONFIG_IPV6) - __vxlan_sock_release(vxlan->vn6_sock); -@@ -2255,6 +2259,15 @@ static void vxlan_cleanup(unsigned long arg) - mod_timer(&vxlan->age_timer, next_timer); - } - -+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan) -+{ -+ struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); -+ -+ spin_lock(&vn->sock_lock); -+ hlist_del_init_rcu(&vxlan->hlist); -+ spin_unlock(&vn->sock_lock); -+} -+ - static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) - { - struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); -@@ -3028,12 +3041,6 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, - static void vxlan_dellink(struct net_device *dev, struct list_head *head) - { - struct vxlan_dev *vxlan = netdev_priv(dev); -- struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); -- -- spin_lock(&vn->sock_lock); -- if (!hlist_unhashed(&vxlan->hlist)) -- hlist_del_rcu(&vxlan->hlist); -- spin_unlock(&vn->sock_lock); - - gro_cells_destroy(&vxlan->gro_cells); - list_del(&vxlan->next); -diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c -index 1f445f357da1..888e9cfef51a 100644 ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -304,7 +304,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) - queue->rx_skbs[id] = skb; - - ref = gnttab_claim_grant_reference(&queue->gref_rx_head); -- BUG_ON((signed short)ref < 0); -+ WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); - queue->grant_rx_ref[id] = ref; - - page = skb_frag_page(&skb_shinfo(skb)->frags[0]); -@@ -437,7 +437,7 @@ static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset, - id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs); - tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++); - ref = gnttab_claim_grant_reference(&queue->gref_tx_head); -- BUG_ON((signed short)ref < 0); -+ WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); - - gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, - gfn, GNTMAP_readonly); -diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c -index 3588a56aabb4..5cbf20ab94aa 100644 ---- a/drivers/scsi/qla2xxx/qla_os.c -+++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -2311,10 +2311,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) - - if (mem_only) { - if (pci_enable_device_mem(pdev)) -- goto probe_out; -+ return ret; - } else { - if (pci_enable_device(pdev)) -- goto probe_out; -+ return ret; - } - - /* This may fail but that's ok */ -@@ -2324,7 +2324,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) - if (!ha) { - ql_log_pci(ql_log_fatal, pdev, 0x0009, - "Unable to allocate memory for ha.\n"); -- goto probe_out; -+ goto disable_device; - } - ql_dbg_pci(ql_dbg_init, pdev, 0x000a, - "Memory allocated for ha=%p.\n", ha); -@@ -2923,7 +2923,7 @@ iospace_config_failed: - kfree(ha); - ha = NULL; - --probe_out: -+disable_device: - pci_disable_device(pdev); - return ret; - } -diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c -index 2fb1e974cc70..e11b1001d1f6 100644 ---- a/drivers/staging/lustre/lustre/lov/lov_pack.c -+++ b/drivers/staging/lustre/lustre/lov/lov_pack.c -@@ -399,18 +399,10 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, - struct lov_mds_md *lmmk = NULL; - int rc, lmm_size; - int lum_size; -- mm_segment_t seg; - - if (!lsm) - return -ENODATA; - -- /* -- * "Switch to kernel segment" to allow copying from kernel space by -- * copy_{to,from}_user(). -- */ -- seg = get_fs(); -- set_fs(KERNEL_DS); -- - /* we only need the header part from user space to get lmm_magic and - * lmm_stripe_count, (the header part is common to v1 and v3) */ - lum_size = sizeof(struct lov_user_md_v1); -@@ -485,6 +477,5 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, - - obd_free_diskmd(exp, &lmmk); - out_set: -- set_fs(seg); - return rc; - } -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index af301414a9f3..60743bf27f37 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -1154,15 +1154,28 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size) - if (cmd->unknown_data_length) { - cmd->data_length = size; - } else if (size != cmd->data_length) { -- pr_warn("TARGET_CORE[%s]: Expected Transfer Length:" -+ pr_warn_ratelimited("TARGET_CORE[%s]: Expected Transfer Length:" - " %u does not match SCSI CDB Length: %u for SAM Opcode:" - " 0x%02x\n", cmd->se_tfo->get_fabric_name(), - cmd->data_length, size, cmd->t_task_cdb[0]); - -- if (cmd->data_direction == DMA_TO_DEVICE && -- cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { -- pr_err("Rejecting underflow/overflow WRITE data\n"); -- return TCM_INVALID_CDB_FIELD; -+ if (cmd->data_direction == DMA_TO_DEVICE) { -+ if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { -+ pr_err_ratelimited("Rejecting underflow/overflow" -+ " for WRITE data CDB\n"); -+ return TCM_INVALID_CDB_FIELD; -+ } -+ /* -+ * Some fabric drivers like iscsi-target still expect to -+ * always reject overflow writes. Reject this case until -+ * full fabric driver level support for overflow writes -+ * is introduced tree-wide. -+ */ -+ if (size > cmd->data_length) { -+ pr_err_ratelimited("Rejecting overflow for" -+ " WRITE control CDB\n"); -+ return TCM_INVALID_CDB_FIELD; -+ } - } - /* - * Reject READ_* or WRITE_* with overflow/underflow for -diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c -index 88246f7e435a..0f23dda60011 100644 ---- a/drivers/tty/serial/ifx6x60.c -+++ b/drivers/tty/serial/ifx6x60.c -@@ -1378,9 +1378,9 @@ static struct spi_driver ifx_spi_driver = { - static void __exit ifx_spi_exit(void) - { - /* unregister */ -+ spi_unregister_driver(&ifx_spi_driver); - tty_unregister_driver(tty_drv); - put_tty_driver(tty_drv); -- spi_unregister_driver(&ifx_spi_driver); - unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); - } - -diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c -index 63a06ab6ba03..235e150d7b81 100644 ---- a/drivers/tty/serial/sh-sci.c -+++ b/drivers/tty/serial/sh-sci.c -@@ -1800,11 +1800,13 @@ static int sci_startup(struct uart_port *port) - - dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); - -+ sci_request_dma(port); -+ - ret = sci_request_irq(s); -- if (unlikely(ret < 0)) -+ if (unlikely(ret < 0)) { -+ sci_free_dma(port); - return ret; -- -- sci_request_dma(port); -+ } - - spin_lock_irqsave(&port->lock, flags); - sci_start_tx(port); -@@ -1834,8 +1836,8 @@ static void sci_shutdown(struct uart_port *port) - } - #endif - -- sci_free_dma(port); - sci_free_irq(s); -+ sci_free_dma(port); - } - - static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, -diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c -index 7cef54334b12..1bb629ab8ecc 100644 ---- a/drivers/tty/tty_io.c -+++ b/drivers/tty/tty_io.c -@@ -2070,13 +2070,12 @@ retry_open: - if (tty) { - mutex_unlock(&tty_mutex); - retval = tty_lock_interruptible(tty); -+ tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */ - if (retval) { - if (retval == -EINTR) - retval = -ERESTARTSYS; - goto err_unref; - } -- /* safe to drop the kref from tty_driver_lookup_tty() */ -- tty_kref_put(tty); - retval = tty_reopen(tty); - if (retval < 0) { - tty_unlock(tty); -diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c -index d09293bc0e04..cff304abb619 100644 ---- a/drivers/tty/tty_mutex.c -+++ b/drivers/tty/tty_mutex.c -@@ -24,10 +24,15 @@ EXPORT_SYMBOL(tty_lock); - - int tty_lock_interruptible(struct tty_struct *tty) - { -+ int ret; -+ - if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) - return -EIO; - tty_kref_get(tty); -- return mutex_lock_interruptible(&tty->legacy_mutex); -+ ret = mutex_lock_interruptible(&tty->legacy_mutex); -+ if (ret) -+ tty_kref_put(tty); -+ return ret; - } - - void __lockfunc tty_unlock(struct tty_struct *tty) -diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c -index 58c8485a0715..923379972707 100644 ---- a/drivers/usb/chipidea/debug.c -+++ b/drivers/usb/chipidea/debug.c -@@ -295,7 +295,8 @@ static int ci_role_show(struct seq_file *s, void *data) - { - struct ci_hdrc *ci = s->private; - -- seq_printf(s, "%s\n", ci_role(ci)->name); -+ if (ci->role != CI_ROLE_END) -+ seq_printf(s, "%s\n", ci_role(ci)->name); - - return 0; - } -diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c -index d8a045fc1fdb..aff086ca97e4 100644 ---- a/drivers/usb/chipidea/udc.c -+++ b/drivers/usb/chipidea/udc.c -@@ -1982,6 +1982,7 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci) - int ci_hdrc_gadget_init(struct ci_hdrc *ci) - { - struct ci_role_driver *rdrv; -+ int ret; - - if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC)) - return -ENXIO; -@@ -1994,7 +1995,10 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci) - rdrv->stop = udc_id_switch_for_host; - rdrv->irq = udc_irq; - rdrv->name = "gadget"; -- ci->roles[CI_ROLE_GADGET] = rdrv; - -- return udc_start(ci); -+ ret = udc_start(ci); -+ if (!ret) -+ ci->roles[CI_ROLE_GADGET] = rdrv; -+ -+ return ret; - } -diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c -index a4f664062e0c..a069726da72a 100644 ---- a/drivers/usb/gadget/function/f_mass_storage.c -+++ b/drivers/usb/gadget/function/f_mass_storage.c -@@ -399,7 +399,11 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) - /* Caller must hold fsg->lock */ - static void wakeup_thread(struct fsg_common *common) - { -- smp_wmb(); /* ensure the write of bh->state is complete */ -+ /* -+ * Ensure the reading of thread_wakeup_needed -+ * and the writing of bh->state are completed -+ */ -+ smp_mb(); - /* Tell the main thread that something has happened */ - common->thread_wakeup_needed = 1; - if (common->thread_task) -@@ -630,7 +634,12 @@ static int sleep_thread(struct fsg_common *common, bool can_freeze) - } - __set_current_state(TASK_RUNNING); - common->thread_wakeup_needed = 0; -- smp_rmb(); /* ensure the latest bh->state is visible */ -+ -+ /* -+ * Ensure the writing of thread_wakeup_needed -+ * and the reading of bh->state are completed -+ */ -+ smp_mb(); - return rc; - } - -diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c -index df2e6f783318..527de56f832f 100644 ---- a/drivers/xen/privcmd.c -+++ b/drivers/xen/privcmd.c -@@ -335,8 +335,8 @@ static int mmap_batch_fn(void *data, int nr, void *state) - st->global_error = 1; - } - } -- st->va += PAGE_SIZE * nr; -- st->index += nr; -+ st->va += XEN_PAGE_SIZE * nr; -+ st->index += nr / XEN_PFN_PER_PAGE; - - return 0; - } -diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c -index 2a2e370399ba..c36a03fa7678 100644 ---- a/fs/btrfs/extent-tree.c -+++ b/fs/btrfs/extent-tree.c -@@ -3854,6 +3854,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, - info->space_info_kobj, "%s", - alloc_name(found->flags)); - if (ret) { -+ percpu_counter_destroy(&found->total_bytes_pinned); - kfree(found); - return ret; - } -diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c -index 353f4bae658c..d4a6eef31854 100644 ---- a/fs/btrfs/file.c -+++ b/fs/btrfs/file.c -@@ -2771,7 +2771,7 @@ static long btrfs_fallocate(struct file *file, int mode, - if (!ret) - ret = btrfs_prealloc_file_range(inode, mode, - range->start, -- range->len, 1 << inode->i_blkbits, -+ range->len, i_blocksize(inode), - offset + len, &alloc_hint); - list_del(&range->list); - kfree(range); -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 3cff6523f27d..863fa0f1972b 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -7318,8 +7318,8 @@ bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end) - int found = false; - void **pagep = NULL; - struct page *page = NULL; -- int start_idx; -- int end_idx; -+ unsigned long start_idx; -+ unsigned long end_idx; - - start_idx = start >> PAGE_CACHE_SHIFT; - -diff --git a/fs/buffer.c b/fs/buffer.c -index 4f4cd959da7c..6f7d519a093b 100644 ---- a/fs/buffer.c -+++ b/fs/buffer.c -@@ -2298,7 +2298,7 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping, - loff_t pos, loff_t *bytes) - { - struct inode *inode = mapping->host; -- unsigned blocksize = 1 << inode->i_blkbits; -+ unsigned int blocksize = i_blocksize(inode); - struct page *page; - void *fsdata; - pgoff_t index, curidx; -@@ -2378,8 +2378,8 @@ int cont_write_begin(struct file *file, struct address_space *mapping, - get_block_t *get_block, loff_t *bytes) - { - struct inode *inode = mapping->host; -- unsigned blocksize = 1 << inode->i_blkbits; -- unsigned zerofrom; -+ unsigned int blocksize = i_blocksize(inode); -+ unsigned int zerofrom; - int err; - - err = cont_expand_zero(file, mapping, pos, bytes); -@@ -2741,7 +2741,7 @@ int nobh_truncate_page(struct address_space *mapping, - struct buffer_head map_bh; - int err; - -- blocksize = 1 << inode->i_blkbits; -+ blocksize = i_blocksize(inode); - length = offset & (blocksize - 1); - - /* Block boundary? Nothing to do */ -@@ -2819,7 +2819,7 @@ int block_truncate_page(struct address_space *mapping, - struct buffer_head *bh; - int err; - -- blocksize = 1 << inode->i_blkbits; -+ blocksize = i_blocksize(inode); - length = offset & (blocksize - 1); - - /* Block boundary? Nothing to do */ -@@ -2931,7 +2931,7 @@ sector_t generic_block_bmap(struct address_space *mapping, sector_t block, - struct inode *inode = mapping->host; - tmp.b_state = 0; - tmp.b_blocknr = 0; -- tmp.b_size = 1 << inode->i_blkbits; -+ tmp.b_size = i_blocksize(inode); - get_block(inode, block, &tmp, 0); - return tmp.b_blocknr; - } -diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c -index b7d218a168fb..c6a1ec110c01 100644 ---- a/fs/ceph/addr.c -+++ b/fs/ceph/addr.c -@@ -697,7 +697,7 @@ static int ceph_writepages_start(struct address_space *mapping, - struct pagevec pvec; - int done = 0; - int rc = 0; -- unsigned wsize = 1 << inode->i_blkbits; -+ unsigned int wsize = i_blocksize(inode); - struct ceph_osd_request *req = NULL; - int do_sync = 0; - loff_t snap_size, i_size; -diff --git a/fs/direct-io.c b/fs/direct-io.c -index 01171d8a6ee9..c772fdf36cd9 100644 ---- a/fs/direct-io.c -+++ b/fs/direct-io.c -@@ -575,7 +575,7 @@ static int dio_set_defer_completion(struct dio *dio) - /* - * Call into the fs to map some more disk blocks. We record the current number - * of available blocks at sdio->blocks_available. These are in units of the -- * fs blocksize, (1 << inode->i_blkbits). -+ * fs blocksize, i_blocksize(inode). - * - * The fs is allowed to map lots of blocks at once. If it wants to do that, - * it uses the passed inode-relative block number as the file offset, as usual. -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 8a456f9b8a44..61d5bfc7318c 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4902,6 +4902,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, - - /* Zero out partial block at the edges of the range */ - ret = ext4_zero_partial_blocks(handle, inode, offset, len); -+ if (ret >= 0) -+ ext4_update_inode_fsync_trans(handle, inode, 1); - - if (file->f_flags & O_SYNC) - ext4_handle_sync(handle); -@@ -5597,6 +5599,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) - ext4_handle_sync(handle); - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); -+ ext4_update_inode_fsync_trans(handle, inode, 1); - - out_stop: - ext4_journal_stop(handle); -@@ -5770,6 +5773,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) - up_write(&EXT4_I(inode)->i_data_sem); - if (IS_SYNC(inode)) - ext4_handle_sync(handle); -+ if (ret >= 0) -+ ext4_update_inode_fsync_trans(handle, inode, 1); - - out_stop: - ext4_journal_stop(handle); -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 0d24ebcd7c9e..8772bfc3415b 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -463,47 +463,27 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, - num = min_t(pgoff_t, end - index, PAGEVEC_SIZE); - nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, - (pgoff_t)num); -- if (nr_pages == 0) { -- if (whence == SEEK_DATA) -- break; -- -- BUG_ON(whence != SEEK_HOLE); -- /* -- * If this is the first time to go into the loop and -- * offset is not beyond the end offset, it will be a -- * hole at this offset -- */ -- if (lastoff == startoff || lastoff < endoff) -- found = 1; -+ if (nr_pages == 0) - break; -- } -- -- /* -- * If this is the first time to go into the loop and -- * offset is smaller than the first page offset, it will be a -- * hole at this offset. -- */ -- if (lastoff == startoff && whence == SEEK_HOLE && -- lastoff < page_offset(pvec.pages[0])) { -- found = 1; -- break; -- } - - for (i = 0; i < nr_pages; i++) { - struct page *page = pvec.pages[i]; - struct buffer_head *bh, *head; - - /* -- * If the current offset is not beyond the end of given -- * range, it will be a hole. -+ * If current offset is smaller than the page offset, -+ * there is a hole at this offset. - */ -- if (lastoff < endoff && whence == SEEK_HOLE && -- page->index > end) { -+ if (whence == SEEK_HOLE && lastoff < endoff && -+ lastoff < page_offset(pvec.pages[i])) { - found = 1; - *offset = lastoff; - goto out; - } - -+ if (page->index > end) -+ goto out; -+ - lock_page(page); - - if (unlikely(page->mapping != inode->i_mapping)) { -@@ -543,20 +523,18 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, - unlock_page(page); - } - -- /* -- * The no. of pages is less than our desired, that would be a -- * hole in there. -- */ -- if (nr_pages < num && whence == SEEK_HOLE) { -- found = 1; -- *offset = lastoff; -+ /* The no. of pages is less than our desired, we are done. */ -+ if (nr_pages < num) - break; -- } - - index = pvec.pages[i - 1]->index + 1; - pagevec_release(&pvec); - } while (index <= end); - -+ if (whence == SEEK_HOLE && lastoff < endoff) { -+ found = 1; -+ *offset = lastoff; -+ } - out: - pagevec_release(&pvec); - return found; -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index ccae64dad40c..1796d1bd9a1d 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -2044,7 +2044,7 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd, - { - struct inode *inode = mpd->inode; - int err; -- ext4_lblk_t blocks = (i_size_read(inode) + (1 << inode->i_blkbits) - 1) -+ ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1) - >> inode->i_blkbits; - - do { -@@ -3793,6 +3793,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) - - inode->i_mtime = inode->i_ctime = ext4_current_time(inode); - ext4_mark_inode_dirty(handle, inode); -+ if (ret >= 0) -+ ext4_update_inode_fsync_trans(handle, inode, 1); - out_stop: - ext4_journal_stop(handle); - out_dio: -@@ -5162,8 +5164,9 @@ static int ext4_expand_extra_isize(struct inode *inode, - /* No extended attributes present */ - if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || - header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { -- memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, -- new_extra_isize); -+ memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + -+ EXT4_I(inode)->i_extra_isize, 0, -+ new_extra_isize - EXT4_I(inode)->i_extra_isize); - EXT4_I(inode)->i_extra_isize = new_extra_isize; - return 0; - } -diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c -index 7861d801b048..05048fcfd602 100644 ---- a/fs/ext4/move_extent.c -+++ b/fs/ext4/move_extent.c -@@ -187,7 +187,7 @@ mext_page_mkuptodate(struct page *page, unsigned from, unsigned to) - if (PageUptodate(page)) - return 0; - -- blocksize = 1 << inode->i_blkbits; -+ blocksize = i_blocksize(inode); - if (!page_has_buffers(page)) - create_empty_buffers(page, blocksize, 0); - -diff --git a/fs/jfs/super.c b/fs/jfs/super.c -index 8f9176caf098..c8d58c5ac8ae 100644 ---- a/fs/jfs/super.c -+++ b/fs/jfs/super.c -@@ -758,7 +758,7 @@ static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, - sb->s_blocksize - offset : toread; - - tmp_bh.b_state = 0; -- tmp_bh.b_size = 1 << inode->i_blkbits; -+ tmp_bh.b_size = i_blocksize(inode); - err = jfs_get_block(inode, blk, &tmp_bh, 0); - if (err) - return err; -@@ -798,7 +798,7 @@ static ssize_t jfs_quota_write(struct super_block *sb, int type, - sb->s_blocksize - offset : towrite; - - tmp_bh.b_state = 0; -- tmp_bh.b_size = 1 << inode->i_blkbits; -+ tmp_bh.b_size = i_blocksize(inode); - err = jfs_get_block(inode, blk, &tmp_bh, 1); - if (err) - goto out; -diff --git a/fs/mpage.c b/fs/mpage.c -index 1480d3a18037..6ade29b19494 100644 ---- a/fs/mpage.c -+++ b/fs/mpage.c -@@ -111,7 +111,7 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block) - SetPageUptodate(page); - return; - } -- create_empty_buffers(page, 1 << inode->i_blkbits, 0); -+ create_empty_buffers(page, i_blocksize(inode), 0); - } - head = page_buffers(page); - page_bh = head; -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index 52ee0b73ab4a..5b21b1ca2341 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -2421,6 +2421,20 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) - } - EXPORT_SYMBOL_GPL(nfs_may_open); - -+static int nfs_execute_ok(struct inode *inode, int mask) -+{ -+ struct nfs_server *server = NFS_SERVER(inode); -+ int ret; -+ -+ if (mask & MAY_NOT_BLOCK) -+ ret = nfs_revalidate_inode_rcu(server, inode); -+ else -+ ret = nfs_revalidate_inode(server, inode); -+ if (ret == 0 && !execute_ok(inode)) -+ ret = -EACCES; -+ return ret; -+} -+ - int nfs_permission(struct inode *inode, int mask) - { - struct rpc_cred *cred; -@@ -2438,6 +2452,9 @@ int nfs_permission(struct inode *inode, int mask) - case S_IFLNK: - goto out; - case S_IFREG: -+ if ((mask & MAY_OPEN) && -+ nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)) -+ return 0; - break; - case S_IFDIR: - /* -@@ -2470,8 +2487,8 @@ force_lookup: - res = PTR_ERR(cred); - } - out: -- if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) -- res = -EACCES; -+ if (!res && (mask & MAY_EXEC)) -+ res = nfs_execute_ok(inode, mask); - - dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n", - inode->i_sb->s_id, inode->i_ino, mask, res); -diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c -index c29d9421bd5e..0976f8dad4ce 100644 ---- a/fs/nfsd/blocklayout.c -+++ b/fs/nfsd/blocklayout.c -@@ -50,7 +50,7 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, - { - struct nfsd4_layout_seg *seg = &args->lg_seg; - struct super_block *sb = inode->i_sb; -- u32 block_size = (1 << inode->i_blkbits); -+ u32 block_size = i_blocksize(inode); - struct pnfs_block_extent *bex; - struct iomap iomap; - u32 device_generation = 0; -@@ -151,7 +151,7 @@ nfsd4_block_proc_layoutcommit(struct inode *inode, - int error; - - nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, -- lcp->lc_up_len, &iomaps, 1 << inode->i_blkbits); -+ lcp->lc_up_len, &iomaps, i_blocksize(inode)); - if (nr_iomaps < 0) - return nfserrno(nr_iomaps); - -diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c -index 7d5351cd67fb..209dbfc50cd4 100644 ---- a/fs/nfsd/nfs4proc.c -+++ b/fs/nfsd/nfs4proc.c -@@ -1690,6 +1690,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, - opdesc->op_get_currentstateid(cstate, &op->u); - op->status = opdesc->op_func(rqstp, cstate, &op->u); - -+ /* Only from SEQUENCE */ -+ if (cstate->status == nfserr_replay_cache) { -+ dprintk("%s NFS4.1 replay from cache\n", __func__); -+ status = op->status; -+ goto out; -+ } - if (!op->status) { - if (opdesc->op_set_currentstateid) - opdesc->op_set_currentstateid(cstate, &op->u); -@@ -1700,14 +1706,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, - if (need_wrongsec_check(rqstp)) - op->status = check_nfsd_access(current_fh->fh_export, rqstp); - } -- - encode_op: -- /* Only from SEQUENCE */ -- if (cstate->status == nfserr_replay_cache) { -- dprintk("%s NFS4.1 replay from cache\n", __func__); -- status = op->status; -- goto out; -- } - if (op->status == nfserr_replay_me) { - op->replay = &cstate->replay_owner->so_replay; - nfsd4_encode_replay(&resp->xdr, op); -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index c3e1cb481fe0..3f68a25f2169 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -2753,9 +2753,16 @@ out_acl: - } - #endif /* CONFIG_NFSD_PNFS */ - if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { -- status = nfsd4_encode_bitmap(xdr, NFSD_SUPPATTR_EXCLCREAT_WORD0, -- NFSD_SUPPATTR_EXCLCREAT_WORD1, -- NFSD_SUPPATTR_EXCLCREAT_WORD2); -+ u32 supp[3]; -+ -+ supp[0] = nfsd_suppattrs0(minorversion); -+ supp[1] = nfsd_suppattrs1(minorversion); -+ supp[2] = nfsd_suppattrs2(minorversion); -+ supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0; -+ supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1; -+ supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2; -+ -+ status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]); - if (status) - goto out; - } -diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c -index a35ae35e6932..cd39b57288c2 100644 ---- a/fs/nilfs2/btnode.c -+++ b/fs/nilfs2/btnode.c -@@ -55,7 +55,7 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) - brelse(bh); - BUG(); - } -- memset(bh->b_data, 0, 1 << inode->i_blkbits); -+ memset(bh->b_data, 0, i_blocksize(inode)); - bh->b_bdev = inode->i_sb->s_bdev; - bh->b_blocknr = blocknr; - set_buffer_mapped(bh); -diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c -index ac2f64943ff4..00877ef0b120 100644 ---- a/fs/nilfs2/inode.c -+++ b/fs/nilfs2/inode.c -@@ -55,7 +55,7 @@ void nilfs_inode_add_blocks(struct inode *inode, int n) - { - struct nilfs_root *root = NILFS_I(inode)->i_root; - -- inode_add_bytes(inode, (1 << inode->i_blkbits) * n); -+ inode_add_bytes(inode, i_blocksize(inode) * n); - if (root) - atomic64_add(n, &root->blocks_count); - } -@@ -64,7 +64,7 @@ void nilfs_inode_sub_blocks(struct inode *inode, int n) - { - struct nilfs_root *root = NILFS_I(inode)->i_root; - -- inode_sub_bytes(inode, (1 << inode->i_blkbits) * n); -+ inode_sub_bytes(inode, i_blocksize(inode) * n); - if (root) - atomic64_sub(n, &root->blocks_count); - } -diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c -index 1125f40233ff..612a2457243d 100644 ---- a/fs/nilfs2/mdt.c -+++ b/fs/nilfs2/mdt.c -@@ -60,7 +60,7 @@ nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block, - set_buffer_mapped(bh); - - kaddr = kmap_atomic(bh->b_page); -- memset(kaddr + bh_offset(bh), 0, 1 << inode->i_blkbits); -+ memset(kaddr + bh_offset(bh), 0, i_blocksize(inode)); - if (init_block) - init_block(inode, bh, kaddr); - flush_dcache_page(bh->b_page); -@@ -503,7 +503,7 @@ void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, - struct nilfs_mdt_info *mi = NILFS_MDT(inode); - - mi->mi_entry_size = entry_size; -- mi->mi_entries_per_block = (1 << inode->i_blkbits) / entry_size; -+ mi->mi_entries_per_block = i_blocksize(inode) / entry_size; - mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); - } - -diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c -index 3b65adaae7e4..2f27c935bd57 100644 ---- a/fs/nilfs2/segment.c -+++ b/fs/nilfs2/segment.c -@@ -719,7 +719,7 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode, - - lock_page(page); - if (!page_has_buffers(page)) -- create_empty_buffers(page, 1 << inode->i_blkbits, 0); -+ create_empty_buffers(page, i_blocksize(inode), 0); - unlock_page(page); - - bh = head = page_buffers(page); -diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c -index e6795c7c76a8..e4184bd2a954 100644 ---- a/fs/ocfs2/aops.c -+++ b/fs/ocfs2/aops.c -@@ -1103,7 +1103,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, - int ret = 0; - struct buffer_head *head, *bh, *wait[2], **wait_bh = wait; - unsigned int block_end, block_start; -- unsigned int bsize = 1 << inode->i_blkbits; -+ unsigned int bsize = i_blocksize(inode); - - if (!page_has_buffers(page)) - create_empty_buffers(page, bsize, 0); -diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c -index 56dd3957cc91..1d738723a41a 100644 ---- a/fs/ocfs2/file.c -+++ b/fs/ocfs2/file.c -@@ -808,7 +808,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, - /* We know that zero_from is block aligned */ - for (block_start = zero_from; block_start < zero_to; - block_start = block_end) { -- block_end = block_start + (1 << inode->i_blkbits); -+ block_end = block_start + i_blocksize(inode); - - /* - * block_start is block-aligned. Bump it by one to force -diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c -index 8f5ccdf81c25..38187300a2b4 100644 ---- a/fs/reiserfs/file.c -+++ b/fs/reiserfs/file.c -@@ -189,7 +189,7 @@ int reiserfs_commit_page(struct inode *inode, struct page *page, - int ret = 0; - - th.t_trans_id = 0; -- blocksize = 1 << inode->i_blkbits; -+ blocksize = i_blocksize(inode); - - if (logit) { - reiserfs_write_lock(s); -diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c -index 3d8e7e671d5b..60ba35087d12 100644 ---- a/fs/reiserfs/inode.c -+++ b/fs/reiserfs/inode.c -@@ -524,7 +524,7 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode, - * referenced in convert_tail_for_hole() that may be called from - * reiserfs_get_block() - */ -- bh_result->b_size = (1 << inode->i_blkbits); -+ bh_result->b_size = i_blocksize(inode); - - ret = reiserfs_get_block(inode, iblock, bh_result, - create | GET_BLOCK_NO_DANGLE); -diff --git a/fs/stat.c b/fs/stat.c -index d4a61d8dc021..004dd77c3b93 100644 ---- a/fs/stat.c -+++ b/fs/stat.c -@@ -31,7 +31,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) - stat->atime = inode->i_atime; - stat->mtime = inode->i_mtime; - stat->ctime = inode->i_ctime; -- stat->blksize = (1 << inode->i_blkbits); -+ stat->blksize = i_blocksize(inode); - stat->blocks = inode->i_blocks; - } - -@@ -454,6 +454,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes) - inode->i_bytes -= 512; - } - } -+EXPORT_SYMBOL(__inode_add_bytes); - - void inode_add_bytes(struct inode *inode, loff_t bytes) - { -diff --git a/fs/udf/inode.c b/fs/udf/inode.c -index 566df9b5a6cb..7be3166ba553 100644 ---- a/fs/udf/inode.c -+++ b/fs/udf/inode.c -@@ -1206,7 +1206,7 @@ int udf_setsize(struct inode *inode, loff_t newsize) - { - int err; - struct udf_inode_info *iinfo; -- int bsize = 1 << inode->i_blkbits; -+ int bsize = i_blocksize(inode); - - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) -diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c -index dc5fae601c24..637e17cb0edd 100644 ---- a/fs/ufs/balloc.c -+++ b/fs/ufs/balloc.c -@@ -81,7 +81,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) - ufs_error (sb, "ufs_free_fragments", - "bit already cleared for fragment %u", i); - } -- -+ -+ inode_sub_bytes(inode, count << uspi->s_fshift); - fs32_add(sb, &ucg->cg_cs.cs_nffree, count); - uspi->cs_total.cs_nffree += count; - fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count); -@@ -183,6 +184,7 @@ do_more: - ufs_error(sb, "ufs_free_blocks", "freeing free fragment"); - } - ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); -+ inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift); - if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) - ufs_clusteracct (sb, ucpi, blkno, 1); - -@@ -494,6 +496,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, - return 0; - } - -+static bool try_add_frags(struct inode *inode, unsigned frags) -+{ -+ unsigned size = frags * i_blocksize(inode); -+ spin_lock(&inode->i_lock); -+ __inode_add_bytes(inode, size); -+ if (unlikely((u32)inode->i_blocks != inode->i_blocks)) { -+ __inode_sub_bytes(inode, size); -+ spin_unlock(&inode->i_lock); -+ return false; -+ } -+ spin_unlock(&inode->i_lock); -+ return true; -+} -+ - static u64 ufs_add_fragments(struct inode *inode, u64 fragment, - unsigned oldcount, unsigned newcount) - { -@@ -530,6 +546,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, - for (i = oldcount; i < newcount; i++) - if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i)) - return 0; -+ -+ if (!try_add_frags(inode, count)) -+ return 0; - /* - * Block can be extended - */ -@@ -647,6 +666,7 @@ cg_found: - ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i); - i = uspi->s_fpb - count; - -+ inode_sub_bytes(inode, i << uspi->s_fshift); - fs32_add(sb, &ucg->cg_cs.cs_nffree, i); - uspi->cs_total.cs_nffree += i; - fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i); -@@ -657,6 +677,8 @@ cg_found: - result = ufs_bitmap_search (sb, ucpi, goal, allocsize); - if (result == INVBLOCK) - return 0; -+ if (!try_add_frags(inode, count)) -+ return 0; - for (i = 0; i < count; i++) - ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i); - -@@ -716,6 +738,8 @@ norot: - return INVBLOCK; - ucpi->c_rotor = result; - gotit: -+ if (!try_add_frags(inode, uspi->s_fpb)) -+ return 0; - blkno = ufs_fragstoblks(result); - ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno); - if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD) -diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c -index a064cf44b143..1f69bb9b1e9d 100644 ---- a/fs/ufs/inode.c -+++ b/fs/ufs/inode.c -@@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to, - - p = ufs_get_direct_data_ptr(uspi, ufsi, block); - tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p), -- new_size, err, locked_page); -+ new_size - (lastfrag & uspi->s_fpbmask), err, -+ locked_page); - return tmp != 0; - } - -@@ -284,7 +285,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index, - goal += uspi->s_fpb; - } - tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), -- goal, uspi->s_fpb, err, locked_page); -+ goal, nfrags, err, locked_page); - - if (!tmp) { - *err = -ENOSPC; -@@ -402,7 +403,9 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff - - if (!create) { - phys64 = ufs_frag_map(inode, offsets, depth); -- goto out; -+ if (phys64) -+ map_bh(bh_result, sb, phys64 + frag); -+ return 0; - } - - /* This code entered only while writing ....? */ -diff --git a/fs/ufs/super.c b/fs/ufs/super.c -index f6390eec02ca..10f364490833 100644 ---- a/fs/ufs/super.c -+++ b/fs/ufs/super.c -@@ -746,6 +746,23 @@ static void ufs_put_super(struct super_block *sb) - return; - } - -+static u64 ufs_max_bytes(struct super_block *sb) -+{ -+ struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; -+ int bits = uspi->s_apbshift; -+ u64 res; -+ -+ if (bits > 21) -+ res = ~0ULL; -+ else -+ res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + -+ (1LL << (3*bits)); -+ -+ if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) -+ return MAX_LFS_FILESIZE; -+ return res << uspi->s_bshift; -+} -+ - static int ufs_fill_super(struct super_block *sb, void *data, int silent) - { - struct ufs_sb_info * sbi; -@@ -1212,6 +1229,7 @@ magic_found: - "fast symlink size (%u)\n", uspi->s_maxsymlinklen); - uspi->s_maxsymlinklen = maxsymlen; - } -+ sb->s_maxbytes = ufs_max_bytes(sb); - sb->s_max_links = UFS_LINK_MAX; - - inode = ufs_iget(sb, UFS_ROOTINO); -diff --git a/fs/ufs/util.h b/fs/ufs/util.h -index 954175928240..3f9463f8cf2f 100644 ---- a/fs/ufs/util.h -+++ b/fs/ufs/util.h -@@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_( - static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, - struct ufs_buffer_head * ubh, unsigned begin, unsigned block) - { -+ u8 mask; - switch (uspi->s_fpb) { - case 8: - return (*ubh_get_addr (ubh, begin + block) == 0xff); - case 4: -- return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); -+ mask = 0x0f << ((block & 0x01) << 2); -+ return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; - case 2: -- return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); -+ mask = 0x03 << ((block & 0x03) << 1); -+ return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; - case 1: -- return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); -+ mask = 0x01 << (block & 0x07); -+ return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; - } - return 0; - } -diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c -index 29e7e5dd5178..187b80267ff9 100644 ---- a/fs/xfs/xfs_aops.c -+++ b/fs/xfs/xfs_aops.c -@@ -288,7 +288,7 @@ xfs_map_blocks( - { - struct xfs_inode *ip = XFS_I(inode); - struct xfs_mount *mp = ip->i_mount; -- ssize_t count = 1 << inode->i_blkbits; -+ ssize_t count = i_blocksize(inode); - xfs_fileoff_t offset_fsb, end_fsb; - int error = 0; - int bmapi_flags = XFS_BMAPI_ENTIRE; -@@ -921,7 +921,7 @@ xfs_aops_discard_page( - break; - } - next_buffer: -- offset += 1 << inode->i_blkbits; -+ offset += i_blocksize(inode); - - } while ((bh = bh->b_this_page) != head); - -@@ -1363,7 +1363,7 @@ xfs_map_trim_size( - offset + mapping_size >= i_size_read(inode)) { - /* limit mapping to block that spans EOF */ - mapping_size = roundup_64(i_size_read(inode) - offset, -- 1 << inode->i_blkbits); -+ i_blocksize(inode)); - } - if (mapping_size > LONG_MAX) - mapping_size = LONG_MAX; -@@ -1395,7 +1395,7 @@ __xfs_get_blocks( - return -EIO; - - offset = (xfs_off_t)iblock << inode->i_blkbits; -- ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); -+ ASSERT(bh_result->b_size >= i_blocksize(inode)); - size = bh_result->b_size; - - if (!create && direct && offset >= i_size_read(inode)) -@@ -1968,7 +1968,7 @@ xfs_vm_set_page_dirty( - if (offset < end_offset) - set_buffer_dirty(bh); - bh = bh->b_this_page; -- offset += 1 << inode->i_blkbits; -+ offset += i_blocksize(inode); - } while (bh != head); - } - /* -diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c -index ceea444dafb4..3dd47307363f 100644 ---- a/fs/xfs/xfs_file.c -+++ b/fs/xfs/xfs_file.c -@@ -947,7 +947,7 @@ xfs_file_fallocate( - if (error) - goto out_unlock; - } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { -- unsigned blksize_mask = (1 << inode->i_blkbits) - 1; -+ unsigned int blksize_mask = i_blocksize(inode) - 1; - - if (offset & blksize_mask || len & blksize_mask) { - error = -EINVAL; -@@ -969,7 +969,7 @@ xfs_file_fallocate( - if (error) - goto out_unlock; - } else if (mode & FALLOC_FL_INSERT_RANGE) { -- unsigned blksize_mask = (1 << inode->i_blkbits) - 1; -+ unsigned int blksize_mask = i_blocksize(inode) - 1; - - new_size = i_size_read(inode) + len; - if (offset & blksize_mask || len & blksize_mask) { -diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c -index e6dae28dfa1a..9beaf192b4bb 100644 ---- a/fs/xfs/xfs_xattr.c -+++ b/fs/xfs/xfs_xattr.c -@@ -180,6 +180,7 @@ xfs_xattr_put_listent( - arraytop = context->count + prefix_len + namelen + 1; - if (arraytop > context->firstu) { - context->count = -1; /* insufficient space */ -+ context->seen_enough = 1; - return 0; - } - offset = (char *)context->alist + context->count; -diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h -index ad2bcf647b9a..210ccc4ea44b 100644 ---- a/include/linux/cgroup.h -+++ b/include/linux/cgroup.h -@@ -340,6 +340,26 @@ static inline bool css_tryget_online(struct cgroup_subsys_state *css) - } - - /** -+ * css_is_dying - test whether the specified css is dying -+ * @css: target css -+ * -+ * Test whether @css is in the process of offlining or already offline. In -+ * most cases, ->css_online() and ->css_offline() callbacks should be -+ * enough; however, the actual offline operations are RCU delayed and this -+ * test returns %true also when @css is scheduled to be offlined. -+ * -+ * This is useful, for example, when the use case requires synchronous -+ * behavior with respect to cgroup removal. cgroup removal schedules css -+ * offlining but the css can seem alive while the operation is being -+ * delayed. If the delay affects user visible semantics, this test can be -+ * used to resolve the situation. -+ */ -+static inline bool css_is_dying(struct cgroup_subsys_state *css) -+{ -+ return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt); -+} -+ -+/** - * css_put - put a css reference - * @css: target css - * -diff --git a/include/linux/fs.h b/include/linux/fs.h -index e1a123760dbf..c8decb7075d6 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -680,6 +680,11 @@ struct inode { - void *i_private; /* fs or device private pointer */ - }; - -+static inline unsigned int i_blocksize(const struct inode *node) -+{ -+ return (1 << node->i_blkbits); -+} -+ - static inline int inode_unhashed(struct inode *inode) - { - return hlist_unhashed(&inode->i_hash); -diff --git a/include/linux/memblock.h b/include/linux/memblock.h -index 24daf8fc4d7c..76b502c6258f 100644 ---- a/include/linux/memblock.h -+++ b/include/linux/memblock.h -@@ -408,12 +408,20 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end) - } - #endif - -+extern unsigned long memblock_reserved_memory_within(phys_addr_t start_addr, -+ phys_addr_t end_addr); - #else - static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align) - { - return 0; - } - -+static inline unsigned long memblock_reserved_memory_within(phys_addr_t start_addr, -+ phys_addr_t end_addr) -+{ -+ return 0; -+} -+ - #endif /* CONFIG_HAVE_MEMBLOCK */ - - #endif /* __KERNEL__ */ -diff --git a/drivers/char/random.c b/drivers/char/random.c -index 8f889c3..1822472 100644 ---- a/drivers/char/random.c -+++ b/drivers/char/random.c -@@ -1849,28 +1849,6 @@ unsigned long get_random_long(void) - EXPORT_SYMBOL(get_random_long); - - /* -- * Same as get_random_int(), but returns unsigned long. -- */ --unsigned long get_random_long(void) --{ -- __u32 *hash; -- unsigned long ret; -- -- if (arch_get_random_long(&ret)) -- return ret; -- -- hash = get_cpu_var(get_random_int_hash); -- -- hash[0] += current->pid + jiffies + random_get_entropy(); -- md5_transform(hash, random_int_secret); -- ret = *(unsigned long *)hash; -- put_cpu_var(get_random_int_hash); -- -- return ret; --} --EXPORT_SYMBOL(get_random_long); -- --/* - * randomize_range() returns a start address such that - * - * [...... .....] -diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h -index e23a9e704536..5b609a3ce3d7 100644 ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -688,6 +688,7 @@ typedef struct pglist_data { - * is the first PFN that needs to be initialised. - */ - unsigned long first_deferred_pfn; -+ unsigned long static_init_size; - #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ - } pg_data_t; - -diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h -index e13bfdf7f314..81fdf4b8aba4 100644 ---- a/include/linux/ptrace.h -+++ b/include/linux/ptrace.h -@@ -50,7 +50,8 @@ extern int ptrace_request(struct task_struct *child, long request, - unsigned long addr, unsigned long data); - extern void ptrace_notify(int exit_code); - extern void __ptrace_link(struct task_struct *child, -- struct task_struct *new_parent); -+ struct task_struct *new_parent, -+ const struct cred *ptracer_cred); - extern void __ptrace_unlink(struct task_struct *child); - extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead); - #define PTRACE_MODE_READ 0x01 -@@ -202,7 +203,7 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - - if (unlikely(ptrace) && current->ptrace) { - child->ptrace = current->ptrace; -- __ptrace_link(child, current->parent); -+ __ptrace_link(child, current->parent, current->ptracer_cred); - - if (child->ptrace & PT_SEIZED) - task_set_jobctl_pending(child, JOBCTL_TRAP_STOP); -@@ -211,6 +212,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) - - set_tsk_thread_flag(child, TIF_SIGPENDING); - } -+ else -+ child->ptracer_cred = NULL; - } - - /** -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index d443d9ab0236..3f61c647fc5c 100644 ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -1084,9 +1084,6 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) - - static inline void skb_sender_cpu_clear(struct sk_buff *skb) - { --#ifdef CONFIG_XPS -- skb->sender_cpu = 0; --#endif - } - - #ifdef NET_SKBUFF_DATA_USES_OFFSET -diff --git a/include/net/ipv6.h b/include/net/ipv6.h -index 9a5c9f013784..ad1d6039185d 100644 ---- a/include/net/ipv6.h -+++ b/include/net/ipv6.h -@@ -958,6 +958,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, - */ - extern const struct proto_ops inet6_stream_ops; - extern const struct proto_ops inet6_dgram_ops; -+extern const struct proto_ops inet6_sockraw_ops; - - struct group_source_req; - struct group_filter; -diff --git a/kernel/cpuset.c b/kernel/cpuset.c -index b271353d5202..3b5e5430f5d0 100644 ---- a/kernel/cpuset.c -+++ b/kernel/cpuset.c -@@ -173,9 +173,9 @@ typedef enum { - } cpuset_flagbits_t; - - /* convenient tests for these bits */ --static inline bool is_cpuset_online(const struct cpuset *cs) -+static inline bool is_cpuset_online(struct cpuset *cs) - { -- return test_bit(CS_ONLINE, &cs->flags); -+ return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css); - } - - static inline int is_cpu_exclusive(const struct cpuset *cs) -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 784ab8fe8714..22350b15b4e7 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -6410,6 +6410,21 @@ static void perf_log_itrace_start(struct perf_event *event) - perf_output_end(&handle); - } - -+static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs) -+{ -+ /* -+ * Due to interrupt latency (AKA "skid"), we may enter the -+ * kernel before taking an overflow, even if the PMU is only -+ * counting user events. -+ * To avoid leaking information to userspace, we must always -+ * reject kernel samples when exclude_kernel is set. -+ */ -+ if (event->attr.exclude_kernel && !user_mode(regs)) -+ return false; -+ -+ return true; -+} -+ - /* - * Generic event overflow handling, sampling. - */ -@@ -6457,6 +6472,12 @@ static int __perf_event_overflow(struct perf_event *event, - } - - /* -+ * For security, drop the skid kernel samples if necessary. -+ */ -+ if (!sample_is_allowed(event, regs)) -+ return ret; -+ -+ /* - * XXX event_limit might not quite work as expected on inherited - * events - */ -diff --git a/kernel/fork.c b/kernel/fork.c -index 0ee630f3ad4b..68cfda1c1800 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -368,7 +368,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) - set_task_stack_end_magic(tsk); - - #ifdef CONFIG_CC_STACKPROTECTOR -- tsk->stack_canary = get_random_int(); -+ tsk->stack_canary = get_random_long(); - #endif - - /* -diff --git a/kernel/ptrace.c b/kernel/ptrace.c -index c7e8ed99c953..5e2cd1030702 100644 ---- a/kernel/ptrace.c -+++ b/kernel/ptrace.c -@@ -28,19 +28,25 @@ - #include - - -+void __ptrace_link(struct task_struct *child, struct task_struct *new_parent, -+ const struct cred *ptracer_cred) -+{ -+ BUG_ON(!list_empty(&child->ptrace_entry)); -+ list_add(&child->ptrace_entry, &new_parent->ptraced); -+ child->parent = new_parent; -+ child->ptracer_cred = get_cred(ptracer_cred); -+} -+ - /* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. - * - * Must be called with the tasklist lock write-held. - */ --void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) -+static void ptrace_link(struct task_struct *child, struct task_struct *new_parent) - { -- BUG_ON(!list_empty(&child->ptrace_entry)); -- list_add(&child->ptrace_entry, &new_parent->ptraced); -- child->parent = new_parent; - rcu_read_lock(); -- child->ptracer_cred = get_cred(__task_cred(new_parent)); -+ __ptrace_link(child, new_parent, __task_cred(new_parent)); - rcu_read_unlock(); - } - -@@ -353,7 +359,7 @@ static int ptrace_attach(struct task_struct *task, long request, - flags |= PT_SEIZED; - task->ptrace = flags; - -- __ptrace_link(task, current); -+ ptrace_link(task, current); - - /* SEIZE doesn't trap tracee on attach */ - if (!seize) -@@ -420,7 +426,7 @@ static int ptrace_traceme(void) - */ - if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_PTRACED; -- __ptrace_link(current, current->real_parent); -+ ptrace_link(current, current->real_parent); - } - } - write_unlock_irq(&tasklist_lock); -diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c -index 0ecef3e4690e..5e6db6b1e3bd 100644 ---- a/lib/test_user_copy.c -+++ b/lib/test_user_copy.c -@@ -58,7 +58,9 @@ static int __init test_user_copy_init(void) - usermem = (char __user *)user_addr; - bad_usermem = (char *)user_addr; - -- /* Legitimate usage: none of these should fail. */ -+ /* -+ * Legitimate usage: none of these copies should fail. -+ */ - ret |= test(copy_from_user(kmem, usermem, PAGE_SIZE), - "legitimate copy_from_user failed"); - ret |= test(copy_to_user(usermem, kmem, PAGE_SIZE), -@@ -68,19 +70,33 @@ static int __init test_user_copy_init(void) - ret |= test(put_user(value, (unsigned long __user *)usermem), - "legitimate put_user failed"); - -- /* Invalid usage: none of these should succeed. */ -+ /* -+ * Invalid usage: none of these copies should succeed. -+ */ -+ -+ /* Reject kernel-to-kernel copies through copy_from_user(). */ - ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE), - PAGE_SIZE), - "illegal all-kernel copy_from_user passed"); -+ -+#if 0 -+ /* -+ * When running with SMAP/PAN/etc, this will Oops the kernel -+ * due to the zeroing of userspace memory on failure. This needs -+ * to be tested in LKDTM instead, since this test module does not -+ * expect to explode. -+ */ - ret |= test(!copy_from_user(bad_usermem, (char __user *)kmem, - PAGE_SIZE), - "illegal reversed copy_from_user passed"); -+#endif - ret |= test(!copy_to_user((char __user *)kmem, kmem + PAGE_SIZE, - PAGE_SIZE), - "illegal all-kernel copy_to_user passed"); - ret |= test(!copy_to_user((char __user *)kmem, bad_usermem, - PAGE_SIZE), - "illegal reversed copy_to_user passed"); -+ - ret |= test(!get_user(value, (unsigned long __user *)kmem), - "illegal get_user passed"); - ret |= test(!put_user(value, (unsigned long __user *)kmem), -diff --git a/mm/memblock.c b/mm/memblock.c -index d300f1329814..f8fab45bfdb7 100644 ---- a/mm/memblock.c -+++ b/mm/memblock.c -@@ -1634,6 +1634,30 @@ static void __init_memblock memblock_dump(struct memblock_type *type, char *name - } - } - -+extern unsigned long __init_memblock -+memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr) -+{ -+ struct memblock_type *type = &memblock.reserved; -+ unsigned long size = 0; -+ int idx; -+ -+ for (idx = 0; idx < type->cnt; idx++) { -+ struct memblock_region *rgn = &type->regions[idx]; -+ phys_addr_t start, end; -+ -+ if (rgn->base + rgn->size < start_addr) -+ continue; -+ if (rgn->base > end_addr) -+ continue; -+ -+ start = rgn->base; -+ end = start + rgn->size; -+ size += end - start; -+ } -+ -+ return size; -+} -+ - void __init_memblock __memblock_dump_all(void) - { - pr_info("MEMBLOCK configuration:\n"); -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 6f9005dcca2e..bd17a6bdf131 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -269,6 +269,26 @@ int page_group_by_mobility_disabled __read_mostly; - #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT - static inline void reset_deferred_meminit(pg_data_t *pgdat) - { -+ unsigned long max_initialise; -+ unsigned long reserved_lowmem; -+ -+ /* -+ * Initialise at least 2G of a node but also take into account that -+ * two large system hashes that can take up 1GB for 0.25TB/node. -+ */ -+ max_initialise = max(2UL << (30 - PAGE_SHIFT), -+ (pgdat->node_spanned_pages >> 8)); -+ -+ /* -+ * Compensate the all the memblock reservations (e.g. crash kernel) -+ * from the initial estimation to make sure we will initialize enough -+ * memory to boot. -+ */ -+ reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn, -+ pgdat->node_start_pfn + max_initialise); -+ max_initialise += reserved_lowmem; -+ -+ pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages); - pgdat->first_deferred_pfn = ULONG_MAX; - } - -@@ -302,10 +322,9 @@ static inline bool update_defer_init(pg_data_t *pgdat, - /* Always populate low zones for address-contrained allocations */ - if (zone_end < pgdat_end_pfn(pgdat)) - return true; -- - /* Initialise at least 2G of the highest zone */ - (*nr_initialised)++; -- if (*nr_initialised > (2UL << (30 - PAGE_SHIFT)) && -+ if ((*nr_initialised > pgdat->static_init_size) && - (pfn & (PAGES_PER_SECTION - 1)) == 0) { - pgdat->first_deferred_pfn = pfn; - return false; -@@ -5343,7 +5362,6 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, - /* pg_data_t should be reset to zero when it's allocated */ - WARN_ON(pgdat->nr_zones || pgdat->classzone_idx); - -- reset_deferred_meminit(pgdat); - pgdat->node_id = nid; - pgdat->node_start_pfn = node_start_pfn; - #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP -@@ -5362,6 +5380,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, - (unsigned long)pgdat->node_mem_map); - #endif - -+ reset_deferred_meminit(pgdat); - free_area_init_core(pgdat); - } - -diff --git a/mm/truncate.c b/mm/truncate.c -index 76e35ad97102..f4c8270f7b84 100644 ---- a/mm/truncate.c -+++ b/mm/truncate.c -@@ -732,7 +732,7 @@ EXPORT_SYMBOL(truncate_setsize); - */ - void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) - { -- int bsize = 1 << inode->i_blkbits; -+ int bsize = i_blocksize(inode); - loff_t rounded_from; - struct page *page; - pgoff_t index; -diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c -index 57be733a99bc..bcb4559e735d 100644 ---- a/net/bridge/br_stp_if.c -+++ b/net/bridge/br_stp_if.c -@@ -166,7 +166,8 @@ static void br_stp_start(struct net_bridge *br) - br_debug(br, "using kernel STP\n"); - - /* To start timers on any ports left in blocking */ -- mod_timer(&br->hello_timer, jiffies + br->hello_time); -+ if (br->dev->flags & IFF_UP) -+ mod_timer(&br->hello_timer, jiffies + br->hello_time); - br_port_state_selection(br); - } - -diff --git a/net/core/dev.c b/net/core/dev.c -index 48399d8ce614..87b8754f34ac 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -182,7 +182,7 @@ EXPORT_SYMBOL(dev_base_lock); - /* protects napi_hash addition/deletion and napi_gen_id */ - static DEFINE_SPINLOCK(napi_hash_lock); - --static unsigned int napi_gen_id; -+static unsigned int napi_gen_id = NR_CPUS; - static DEFINE_HASHTABLE(napi_hash, 8); - - static seqcount_t devnet_rename_seq; -@@ -3049,7 +3049,9 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev, - int queue_index = 0; - - #ifdef CONFIG_XPS -- if (skb->sender_cpu == 0) -+ u32 sender_cpu = skb->sender_cpu - 1; -+ -+ if (sender_cpu >= (u32)NR_CPUS) - skb->sender_cpu = raw_smp_processor_id() + 1; - #endif - -@@ -4726,25 +4728,22 @@ EXPORT_SYMBOL_GPL(napi_by_id); - - void napi_hash_add(struct napi_struct *napi) - { -- if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) { -+ if (test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) -+ return; - -- spin_lock(&napi_hash_lock); -+ spin_lock(&napi_hash_lock); - -- /* 0 is not a valid id, we also skip an id that is taken -- * we expect both events to be extremely rare -- */ -- napi->napi_id = 0; -- while (!napi->napi_id) { -- napi->napi_id = ++napi_gen_id; -- if (napi_by_id(napi->napi_id)) -- napi->napi_id = 0; -- } -+ /* 0..NR_CPUS+1 range is reserved for sender_cpu use */ -+ do { -+ if (unlikely(++napi_gen_id < NR_CPUS + 1)) -+ napi_gen_id = NR_CPUS + 1; -+ } while (napi_by_id(napi_gen_id)); -+ napi->napi_id = napi_gen_id; - -- hlist_add_head_rcu(&napi->napi_hash_node, -- &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); -+ hlist_add_head_rcu(&napi->napi_hash_node, -+ &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); - -- spin_unlock(&napi_hash_lock); -- } -+ spin_unlock(&napi_hash_lock); - } - EXPORT_SYMBOL_GPL(napi_hash_add); - -diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c -index afc18e9ca94a..967a47ff78a4 100644 ---- a/net/ipv4/af_inet.c -+++ b/net/ipv4/af_inet.c -@@ -1014,7 +1014,7 @@ static struct inet_protosw inetsw_array[] = - .type = SOCK_DGRAM, - .protocol = IPPROTO_ICMP, - .prot = &ping_prot, -- .ops = &inet_dgram_ops, -+ .ops = &inet_sockraw_ops, - .flags = INET_PROTOSW_REUSE, - }, - -diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c -index 882caa4e72bc..aafe68134763 100644 ---- a/net/ipv4/tcp_cong.c -+++ b/net/ipv4/tcp_cong.c -@@ -183,6 +183,7 @@ void tcp_init_congestion_control(struct sock *sk) - { - const struct inet_connection_sock *icsk = inet_csk(sk); - -+ tcp_sk(sk)->prior_ssthresh = 0; - if (icsk->icsk_ca_ops->init) - icsk->icsk_ca_ops->init(sk); - if (tcp_ca_needs_ecn(sk)) -diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c -index 568bc0a52ca1..9e2ea4ae840d 100644 ---- a/net/ipv6/ip6_offload.c -+++ b/net/ipv6/ip6_offload.c -@@ -121,8 +121,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, - - if (udpfrag) { - int err = ip6_find_1stfragopt(skb, &prevhdr); -- if (err < 0) -+ if (err < 0) { -+ kfree_skb_list(segs); - return ERR_PTR(err); -+ } - fptr = (struct frag_hdr *)((u8 *)ipv6h + err); - fptr->frag_off = htons(offset); - if (skb->next) -diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c -index 3e55447b63a4..a830b68e63c9 100644 ---- a/net/ipv6/ping.c -+++ b/net/ipv6/ping.c -@@ -50,7 +50,7 @@ static struct inet_protosw pingv6_protosw = { - .type = SOCK_DGRAM, - .protocol = IPPROTO_ICMPV6, - .prot = &pingv6_prot, -- .ops = &inet6_dgram_ops, -+ .ops = &inet6_sockraw_ops, - .flags = INET_PROTOSW_REUSE, - }; - -diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c -index c93ede16795d..4d52a0e2f60d 100644 ---- a/net/ipv6/raw.c -+++ b/net/ipv6/raw.c -@@ -1303,7 +1303,7 @@ void raw6_proc_exit(void) - #endif /* CONFIG_PROC_FS */ - - /* Same as inet6_dgram_ops, sans udp_poll. */ --static const struct proto_ops inet6_sockraw_ops = { -+const struct proto_ops inet6_sockraw_ops = { - .family = PF_INET6, - .owner = THIS_MODULE, - .release = inet6_release, -diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c -index 0e015906f9ca..07d36573f50b 100644 ---- a/net/ipv6/xfrm6_mode_ro.c -+++ b/net/ipv6/xfrm6_mode_ro.c -@@ -47,6 +47,8 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) - iph = ipv6_hdr(skb); - - hdr_len = x->type->hdr_offset(x, skb, &prevhdr); -+ if (hdr_len < 0) -+ return hdr_len; - skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); - skb_set_network_header(skb, -x->props.header_len); - skb->transport_header = skb->network_header + hdr_len; -diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c -index 4e344105b3fd..1d3bbe6e1183 100644 ---- a/net/ipv6/xfrm6_mode_transport.c -+++ b/net/ipv6/xfrm6_mode_transport.c -@@ -28,6 +28,8 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) - iph = ipv6_hdr(skb); - - hdr_len = x->type->hdr_offset(x, skb, &prevhdr); -+ if (hdr_len < 0) -+ return hdr_len; - skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); - skb_set_network_header(skb, -x->props.header_len); - skb->transport_header = skb->network_header + hdr_len; -diff --git a/security/keys/key.c b/security/keys/key.c -index 534808915371..09c10b181881 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -934,12 +934,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - /* the key must be writable */ - ret = key_permission(key_ref, KEY_NEED_WRITE); - if (ret < 0) -- goto error; -+ return ret; - - /* attempt to update it if supported */ -- ret = -EOPNOTSUPP; - if (!key->type->update) -- goto error; -+ return -EOPNOTSUPP; - - memset(&prep, 0, sizeof(prep)); - prep.data = payload; -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 442e350c209d..671709d8610d 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -97,7 +97,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, - /* pull the payload in if one was supplied */ - payload = NULL; - -- if (_payload) { -+ if (plen) { - ret = -ENOMEM; - payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); - if (!payload) { -@@ -327,7 +327,7 @@ long keyctl_update_key(key_serial_t id, - - /* pull the payload in if one was supplied */ - payload = NULL; -- if (_payload) { -+ if (plen) { - ret = -ENOMEM; - payload = kmalloc(plen, GFP_KERNEL); - if (!payload) -diff --git a/sound/core/timer.c b/sound/core/timer.c -index 278a332f97bd..48eaccba82a3 100644 ---- a/sound/core/timer.c -+++ b/sound/core/timer.c -@@ -1621,6 +1621,7 @@ static int snd_timer_user_tselect(struct file *file, - if (err < 0) - goto __err; - -+ tu->qhead = tu->qtail = tu->qused = 0; - kfree(tu->queue); - tu->queue = NULL; - kfree(tu->tqueue); -@@ -1958,6 +1959,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - - tu = file->private_data; - unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); -+ mutex_lock(&tu->ioctl_lock); - spin_lock_irq(&tu->qlock); - while ((long)count - result >= unit) { - while (!tu->qused) { -@@ -1973,7 +1975,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - add_wait_queue(&tu->qchange_sleep, &wait); - - spin_unlock_irq(&tu->qlock); -+ mutex_unlock(&tu->ioctl_lock); - schedule(); -+ mutex_lock(&tu->ioctl_lock); - spin_lock_irq(&tu->qlock); - - remove_wait_queue(&tu->qchange_sleep, &wait); -@@ -1993,7 +1997,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - tu->qused--; - spin_unlock_irq(&tu->qlock); - -- mutex_lock(&tu->ioctl_lock); - if (tu->tread) { - if (copy_to_user(buffer, &tu->tqueue[qhead], - sizeof(struct snd_timer_tread))) -@@ -2003,7 +2006,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - sizeof(struct snd_timer_read))) - err = -EFAULT; - } -- mutex_unlock(&tu->ioctl_lock); - - spin_lock_irq(&tu->qlock); - if (err < 0) -@@ -2013,6 +2015,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - } - _error: - spin_unlock_irq(&tu->qlock); -+ mutex_unlock(&tu->ioctl_lock); - return result > 0 ? result : err; - } - -diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c -index a1305f827a98..fa6b74a304a7 100644 ---- a/sound/soc/soc-core.c -+++ b/sound/soc/soc-core.c -@@ -1775,6 +1775,9 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) - for (i = 0; i < card->num_aux_devs; i++) - soc_remove_aux_dev(card, i); - -+ /* free the ALSA card at first; this syncs with pending operations */ -+ snd_card_free(card->snd_card); -+ - /* remove and free each DAI */ - soc_remove_dai_links(card); - -@@ -1786,9 +1789,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) - - snd_soc_dapm_free(&card->dapm); - -- snd_card_free(card->snd_card); - return 0; -- - } - - /* removes a socdev */ diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.72-73.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.72-73.patch deleted file mode 100644 index 43d7eb9c8..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.72-73.patch +++ /dev/null @@ -1,2192 +0,0 @@ -diff --git a/Makefile b/Makefile -index 94d663c935c0..ba5a70b6e32c 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 72 -+SUBLEVEL = 73 - EXTRAVERSION = - NAME = Blurry Fish Butt - -@@ -789,7 +789,7 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=date-time) - KBUILD_ARFLAGS := $(call ar-option,D) - - # check for 'asm goto' --ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y) -+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y) - KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO - KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO - endif -diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi -index 4b0ec0703825..8ca9217204a0 100644 ---- a/arch/arm/boot/dts/imx6dl.dtsi -+++ b/arch/arm/boot/dts/imx6dl.dtsi -@@ -30,7 +30,7 @@ - /* kHz uV */ - 996000 1250000 - 792000 1175000 -- 396000 1075000 -+ 396000 1150000 - >; - fsl,soc-operating-points = < - /* ARM kHz SOC-PU uV */ -diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S -index 7460df3eec6b..4612ed7ec2e5 100644 ---- a/arch/s390/kernel/entry.S -+++ b/arch/s390/kernel/entry.S -@@ -229,12 +229,17 @@ ENTRY(sie64a) - lctlg %c1,%c1,__LC_USER_ASCE # load primary asce - .Lsie_done: - # some program checks are suppressing. C code (e.g. do_protection_exception) --# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other --# instructions between sie64a and .Lsie_done should not cause program --# interrupts. So lets use a nop (47 00 00 00) as a landing pad. -+# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There -+# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable. -+# Other instructions between sie64a and .Lsie_done should not cause program -+# interrupts. So lets use 3 nops as a landing pad for all possible rewinds. - # See also .Lcleanup_sie --.Lrewind_pad: -- nop 0 -+.Lrewind_pad6: -+ nopr 7 -+.Lrewind_pad4: -+ nopr 7 -+.Lrewind_pad2: -+ nopr 7 - .globl sie_exit - sie_exit: - lg %r14,__SF_EMPTY+8(%r15) # load guest register save area -@@ -247,7 +252,9 @@ sie_exit: - stg %r14,__SF_EMPTY+16(%r15) # set exit reason code - j sie_exit - -- EX_TABLE(.Lrewind_pad,.Lsie_fault) -+ EX_TABLE(.Lrewind_pad6,.Lsie_fault) -+ EX_TABLE(.Lrewind_pad4,.Lsie_fault) -+ EX_TABLE(.Lrewind_pad2,.Lsie_fault) - EX_TABLE(sie_exit,.Lsie_fault) - #endif - -diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c -index ef7d6c8fea66..f354fd84adeb 100644 ---- a/arch/s390/mm/vmem.c -+++ b/arch/s390/mm/vmem.c -@@ -372,7 +372,7 @@ void __init vmem_map_init(void) - ro_end = (unsigned long)&_eshared & PAGE_MASK; - for_each_memblock(memory, reg) { - start = reg->base; -- end = reg->base + reg->size - 1; -+ end = reg->base + reg->size; - if (start >= ro_end || end <= ro_start) - vmem_add_mem(start, end - start, 0); - else if (start >= ro_start && end <= ro_end) -diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c -index d21cd625c0de..cc97a43268ee 100644 ---- a/arch/sparc/kernel/traps_64.c -+++ b/arch/sparc/kernel/traps_64.c -@@ -85,7 +85,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p) - - void bad_trap(struct pt_regs *regs, long lvl) - { -- char buffer[32]; -+ char buffer[36]; - siginfo_t info; - - if (notify_die(DIE_TRAP, "bad trap", regs, -@@ -116,7 +116,7 @@ void bad_trap(struct pt_regs *regs, long lvl) - - void bad_trap_tl1(struct pt_regs *regs, long lvl) - { -- char buffer[32]; -+ char buffer[36]; - - if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs, - 0, lvl, SIGTRAP) == NOTIFY_STOP) -diff --git a/arch/xtensa/include/asm/irq.h b/arch/xtensa/include/asm/irq.h -index f71f88ea7646..19707db966f1 100644 ---- a/arch/xtensa/include/asm/irq.h -+++ b/arch/xtensa/include/asm/irq.h -@@ -29,7 +29,8 @@ static inline void variant_irq_disable(unsigned int irq) { } - # define PLATFORM_NR_IRQS 0 - #endif - #define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS --#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS) -+#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS + 1) -+#define XTENSA_PIC_LINUX_IRQ(hwirq) ((hwirq) + 1) - - #if VARIANT_NR_IRQS == 0 - static inline void variant_init_irq(void) { } -diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c -index 4ac3d23161cf..441694464b1e 100644 ---- a/arch/xtensa/kernel/irq.c -+++ b/arch/xtensa/kernel/irq.c -@@ -34,11 +34,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs) - { - int irq = irq_find_mapping(NULL, hwirq); - -- if (hwirq >= NR_IRQS) { -- printk(KERN_EMERG "%s: cannot handle IRQ %d\n", -- __func__, hwirq); -- } -- - #ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 1KB free? */ - { -diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h -index dbeea2b440a1..1fda7e20dfcb 100644 ---- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h -+++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h -@@ -24,16 +24,18 @@ - - /* Interrupt configuration. */ - --#define PLATFORM_NR_IRQS 10 -+#define PLATFORM_NR_IRQS 0 - - /* Default assignment of LX60 devices to external interrupts. */ - - #ifdef CONFIG_XTENSA_MX - #define DUART16552_INTNUM XCHAL_EXTINT3_NUM - #define OETH_IRQ XCHAL_EXTINT4_NUM -+#define C67X00_IRQ XCHAL_EXTINT8_NUM - #else - #define DUART16552_INTNUM XCHAL_EXTINT0_NUM - #define OETH_IRQ XCHAL_EXTINT1_NUM -+#define C67X00_IRQ XCHAL_EXTINT5_NUM - #endif - - /* -@@ -63,5 +65,5 @@ - - #define C67X00_PADDR (XCHAL_KIO_PADDR + 0x0D0D0000) - #define C67X00_SIZE 0x10 --#define C67X00_IRQ 5 -+ - #endif /* __XTENSA_XTAVNET_HARDWARE_H */ -diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c -index e9f65f79cf2e..d1e9439fad45 100644 ---- a/arch/xtensa/platforms/xtfpga/setup.c -+++ b/arch/xtensa/platforms/xtfpga/setup.c -@@ -209,8 +209,8 @@ static struct resource ethoc_res[] = { - .flags = IORESOURCE_MEM, - }, - [2] = { /* IRQ number */ -- .start = OETH_IRQ, -- .end = OETH_IRQ, -+ .start = XTENSA_PIC_LINUX_IRQ(OETH_IRQ), -+ .end = XTENSA_PIC_LINUX_IRQ(OETH_IRQ), - .flags = IORESOURCE_IRQ, - }, - }; -@@ -246,8 +246,8 @@ static struct resource c67x00_res[] = { - .flags = IORESOURCE_MEM, - }, - [1] = { /* IRQ number */ -- .start = C67X00_IRQ, -- .end = C67X00_IRQ, -+ .start = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ), -+ .end = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ), - .flags = IORESOURCE_IRQ, - }, - }; -@@ -280,7 +280,7 @@ static struct resource serial_resource = { - static struct plat_serial8250_port serial_platform_data[] = { - [0] = { - .mapbase = DUART16552_PADDR, -- .irq = DUART16552_INTNUM, -+ .irq = XTENSA_PIC_LINUX_IRQ(DUART16552_INTNUM), - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | - UPF_IOREMAP, - .iotype = UPIO_MEM32, -diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c -index 93e7c1b32edd..5610cd537da7 100644 ---- a/block/partitions/msdos.c -+++ b/block/partitions/msdos.c -@@ -300,6 +300,8 @@ static void parse_bsd(struct parsed_partitions *state, - continue; - bsd_start = le32_to_cpu(p->p_offset); - bsd_size = le32_to_cpu(p->p_size); -+ if (memcmp(flavour, "bsd\0", 4) == 0) -+ bsd_start += offset; - if (offset == bsd_start && size == bsd_size) - /* full parent partition, we have it already */ - continue; -diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c -index 3252429f96af..3a20dc594338 100644 ---- a/drivers/base/power/runtime.c -+++ b/drivers/base/power/runtime.c -@@ -889,13 +889,13 @@ int __pm_runtime_idle(struct device *dev, int rpmflags) - unsigned long flags; - int retval; - -- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); -- - if (rpmflags & RPM_GET_PUT) { - if (!atomic_dec_and_test(&dev->power.usage_count)) - return 0; - } - -+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); -+ - spin_lock_irqsave(&dev->power.lock, flags); - retval = rpm_idle(dev, rpmflags); - spin_unlock_irqrestore(&dev->power.lock, flags); -@@ -921,13 +921,13 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags) - unsigned long flags; - int retval; - -- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); -- - if (rpmflags & RPM_GET_PUT) { - if (!atomic_dec_and_test(&dev->power.usage_count)) - return 0; - } - -+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); -+ - spin_lock_irqsave(&dev->power.lock, flags); - retval = rpm_suspend(dev, rpmflags); - spin_unlock_irqrestore(&dev->power.lock, flags); -@@ -952,7 +952,8 @@ int __pm_runtime_resume(struct device *dev, int rpmflags) - unsigned long flags; - int retval; - -- might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe); -+ might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe && -+ dev->power.runtime_status != RPM_ACTIVE); - - if (rpmflags & RPM_GET_PUT) - atomic_inc(&dev->power.usage_count); -diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h -index 05f6522c0457..b92139e9b9d8 100644 ---- a/drivers/gpu/drm/ast/ast_drv.h -+++ b/drivers/gpu/drm/ast/ast_drv.h -@@ -113,6 +113,7 @@ struct ast_private { - struct ttm_bo_kmap_obj cache_kmap; - int next_cursor; - bool support_wide_screen; -+ bool DisableP2A; - - enum ast_tx_chip tx_chip_type; - u8 dp501_maxclk; -diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c -index 9b8f0b975ca6..6c021165ca67 100644 ---- a/drivers/gpu/drm/ast/ast_main.c -+++ b/drivers/gpu/drm/ast/ast_main.c -@@ -124,6 +124,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - } else - *need_post = false; - -+ /* Check P2A Access */ -+ ast->DisableP2A = true; -+ data = ast_read32(ast, 0xf004); -+ if (data != 0xFFFFFFFF) -+ ast->DisableP2A = false; -+ - /* Check if we support wide screen */ - switch (ast->chip) { - case AST1180: -@@ -140,15 +146,17 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - ast->support_wide_screen = true; - else { - ast->support_wide_screen = false; -- /* Read SCU7c (silicon revision register) */ -- ast_write32(ast, 0xf004, 0x1e6e0000); -- ast_write32(ast, 0xf000, 0x1); -- data = ast_read32(ast, 0x1207c); -- data &= 0x300; -- if (ast->chip == AST2300 && data == 0x0) /* ast1300 */ -- ast->support_wide_screen = true; -- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */ -- ast->support_wide_screen = true; -+ if (ast->DisableP2A == false) { -+ /* Read SCU7c (silicon revision register) */ -+ ast_write32(ast, 0xf004, 0x1e6e0000); -+ ast_write32(ast, 0xf000, 0x1); -+ data = ast_read32(ast, 0x1207c); -+ data &= 0x300; -+ if (ast->chip == AST2300 && data == 0x0) /* ast1300 */ -+ ast->support_wide_screen = true; -+ if (ast->chip == AST2400 && data == 0x100) /* ast1400 */ -+ ast->support_wide_screen = true; -+ } - } - break; - } -@@ -216,80 +224,81 @@ static int ast_get_dram_info(struct drm_device *dev) - uint32_t data, data2; - uint32_t denum, num, div, ref_pll; - -- ast_write32(ast, 0xf004, 0x1e6e0000); -- ast_write32(ast, 0xf000, 0x1); -- -- -- ast_write32(ast, 0x10000, 0xfc600309); -- -- do { -- if (pci_channel_offline(dev->pdev)) -- return -EIO; -- } while (ast_read32(ast, 0x10000) != 0x01); -- data = ast_read32(ast, 0x10004); -- -- if (data & 0x40) -+ if (ast->DisableP2A) -+ { - ast->dram_bus_width = 16; -+ ast->dram_type = AST_DRAM_1Gx16; -+ ast->mclk = 396; -+ } - else -- ast->dram_bus_width = 32; -+ { -+ ast_write32(ast, 0xf004, 0x1e6e0000); -+ ast_write32(ast, 0xf000, 0x1); -+ data = ast_read32(ast, 0x10004); -+ -+ if (data & 0x40) -+ ast->dram_bus_width = 16; -+ else -+ ast->dram_bus_width = 32; -+ -+ if (ast->chip == AST2300 || ast->chip == AST2400) { -+ switch (data & 0x03) { -+ case 0: -+ ast->dram_type = AST_DRAM_512Mx16; -+ break; -+ default: -+ case 1: -+ ast->dram_type = AST_DRAM_1Gx16; -+ break; -+ case 2: -+ ast->dram_type = AST_DRAM_2Gx16; -+ break; -+ case 3: -+ ast->dram_type = AST_DRAM_4Gx16; -+ break; -+ } -+ } else { -+ switch (data & 0x0c) { -+ case 0: -+ case 4: -+ ast->dram_type = AST_DRAM_512Mx16; -+ break; -+ case 8: -+ if (data & 0x40) -+ ast->dram_type = AST_DRAM_1Gx16; -+ else -+ ast->dram_type = AST_DRAM_512Mx32; -+ break; -+ case 0xc: -+ ast->dram_type = AST_DRAM_1Gx32; -+ break; -+ } -+ } - -- if (ast->chip == AST2300 || ast->chip == AST2400) { -- switch (data & 0x03) { -- case 0: -- ast->dram_type = AST_DRAM_512Mx16; -- break; -- default: -- case 1: -- ast->dram_type = AST_DRAM_1Gx16; -- break; -- case 2: -- ast->dram_type = AST_DRAM_2Gx16; -- break; -+ data = ast_read32(ast, 0x10120); -+ data2 = ast_read32(ast, 0x10170); -+ if (data2 & 0x2000) -+ ref_pll = 14318; -+ else -+ ref_pll = 12000; -+ -+ denum = data & 0x1f; -+ num = (data & 0x3fe0) >> 5; -+ data = (data & 0xc000) >> 14; -+ switch (data) { - case 3: -- ast->dram_type = AST_DRAM_4Gx16; -- break; -- } -- } else { -- switch (data & 0x0c) { -- case 0: -- case 4: -- ast->dram_type = AST_DRAM_512Mx16; -+ div = 0x4; - break; -- case 8: -- if (data & 0x40) -- ast->dram_type = AST_DRAM_1Gx16; -- else -- ast->dram_type = AST_DRAM_512Mx32; -+ case 2: -+ case 1: -+ div = 0x2; - break; -- case 0xc: -- ast->dram_type = AST_DRAM_1Gx32; -+ default: -+ div = 0x1; - break; - } -+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); - } -- -- data = ast_read32(ast, 0x10120); -- data2 = ast_read32(ast, 0x10170); -- if (data2 & 0x2000) -- ref_pll = 14318; -- else -- ref_pll = 12000; -- -- denum = data & 0x1f; -- num = (data & 0x3fe0) >> 5; -- data = (data & 0xc000) >> 14; -- switch (data) { -- case 3: -- div = 0x4; -- break; -- case 2: -- case 1: -- div = 0x2; -- break; -- default: -- div = 0x1; -- break; -- } -- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); - return 0; - } - -diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c -index 30672a3df8a9..270e8fb2803f 100644 ---- a/drivers/gpu/drm/ast/ast_post.c -+++ b/drivers/gpu/drm/ast/ast_post.c -@@ -375,12 +375,20 @@ void ast_post_gpu(struct drm_device *dev) - ast_enable_mmio(dev); - ast_set_def_ext_reg(dev); - -- if (ast->chip == AST2300 || ast->chip == AST2400) -- ast_init_dram_2300(dev); -- else -- ast_init_dram_reg(dev); -+ if (ast->DisableP2A == false) -+ { -+ if (ast->chip == AST2300 || ast->chip == AST2400) -+ ast_init_dram_2300(dev); -+ else -+ ast_init_dram_reg(dev); - -- ast_init_3rdtx(dev); -+ ast_init_3rdtx(dev); -+ } -+ else -+ { -+ if (ast->tx_chip_type != AST_TX_NONE) -+ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ -+ } - } - - /* AST 2300 DRAM settings */ -diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c -index 58a3f7cf2fb3..00de1bf81519 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_display.c -+++ b/drivers/gpu/drm/nouveau/nouveau_display.c -@@ -370,7 +370,8 @@ nouveau_display_init(struct drm_device *dev) - return ret; - - /* enable polling for external displays */ -- drm_kms_helper_poll_enable(dev); -+ if (!dev->mode_config.poll_enabled) -+ drm_kms_helper_poll_enable(dev); - - /* enable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c -index d236fc7c425b..91a61d2cca88 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c -@@ -743,7 +743,10 @@ nouveau_pmops_runtime_resume(struct device *dev) - pci_set_master(pdev); - - ret = nouveau_do_resume(drm_dev, true); -- drm_kms_helper_poll_enable(drm_dev); -+ -+ if (!drm_dev->mode_config.poll_enabled) -+ drm_kms_helper_poll_enable(drm_dev); -+ - /* do magic */ - nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25)); - vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); -diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h -index 2e3a62d38fe9..1621c8ae0fa0 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fence.h -+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h -@@ -99,6 +99,7 @@ struct nv84_fence_priv { - struct nouveau_bo *bo; - struct nouveau_bo *bo_gart; - u32 *suspend; -+ struct mutex mutex; - }; - - u64 nv84_fence_crtc(struct nouveau_channel *, int); -diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c -index 6ae1b3494bcd..b7b961233949 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_usif.c -+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c -@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) - if (nvif_unpack(argv->v0, 0, 0, true)) { - /* block access to objects not created via this interface */ - owner = argv->v0.owner; -- if (argv->v0.object == 0ULL) -+ if (argv->v0.object == 0ULL && -+ argv->v0.type != NVIF_IOCTL_V0_DEL) - argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */ - else - argv->v0.owner = NVDRM_OBJECT_USIF; -diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c -index 412c5be5a9ca..7bc26eceda66 100644 ---- a/drivers/gpu/drm/nouveau/nv84_fence.c -+++ b/drivers/gpu/drm/nouveau/nv84_fence.c -@@ -121,8 +121,10 @@ nv84_fence_context_del(struct nouveau_channel *chan) - } - - nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); -+ mutex_lock(&priv->mutex); - nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); - nouveau_bo_vma_del(priv->bo, &fctx->vma); -+ mutex_unlock(&priv->mutex); - nouveau_fence_context_del(&fctx->base); - chan->fence = NULL; - nouveau_fence_context_free(&fctx->base); -@@ -148,11 +150,13 @@ nv84_fence_context_new(struct nouveau_channel *chan) - fctx->base.sync32 = nv84_fence_sync32; - fctx->base.sequence = nv84_fence_read(chan); - -+ mutex_lock(&priv->mutex); - ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma); - if (ret == 0) { - ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm, - &fctx->vma_gart); - } -+ mutex_unlock(&priv->mutex); - - /* map display semaphore buffers into channel's vm */ - for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { -@@ -232,6 +236,8 @@ nv84_fence_create(struct nouveau_drm *drm) - priv->base.context_base = fence_context_alloc(priv->base.contexts); - priv->base.uevent = true; - -+ mutex_init(&priv->mutex); -+ - /* Use VRAM if there is any ; otherwise fallback to system memory */ - domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM : - /* -diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c -index 630bce68bf38..b61db9db3ca5 100644 ---- a/drivers/i2c/busses/i2c-piix4.c -+++ b/drivers/i2c/busses/i2c-piix4.c -@@ -54,7 +54,7 @@ - #define SMBSLVDAT (0xC + piix4_smba) - - /* count for request_region */ --#define SMBIOSIZE 8 -+#define SMBIOSIZE 9 - - /* PCI Address Constants */ - #define SMBBA 0x090 -diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c -index bb3ac5fe5846..72a391e01011 100644 ---- a/drivers/irqchip/irq-xtensa-mx.c -+++ b/drivers/irqchip/irq-xtensa-mx.c -@@ -142,7 +142,7 @@ static struct irq_chip xtensa_mx_irq_chip = { - int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent) - { - struct irq_domain *root_domain = -- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0, -+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0, - &xtensa_mx_irq_domain_ops, - &xtensa_mx_irq_chip); - irq_set_default_host(root_domain); -diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c -index 472ae1770964..f728755fa292 100644 ---- a/drivers/irqchip/irq-xtensa-pic.c -+++ b/drivers/irqchip/irq-xtensa-pic.c -@@ -89,7 +89,7 @@ static struct irq_chip xtensa_irq_chip = { - int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent) - { - struct irq_domain *root_domain = -- irq_domain_add_legacy(NULL, NR_IRQS, 0, 0, -+ irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0, - &xtensa_irq_domain_ops, &xtensa_irq_chip); - irq_set_default_host(root_domain); - return 0; -diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c -index ac7288240d55..f089fa954f42 100644 ---- a/drivers/net/ethernet/adaptec/starfire.c -+++ b/drivers/net/ethernet/adaptec/starfire.c -@@ -1153,6 +1153,12 @@ static void init_ring(struct net_device *dev) - if (skb == NULL) - break; - np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); -+ if (pci_dma_mapping_error(np->pci_dev, -+ np->rx_info[i].mapping)) { -+ dev_kfree_skb(skb); -+ np->rx_info[i].skb = NULL; -+ break; -+ } - /* Grrr, we cannot offset to correctly align the IP header. */ - np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); - } -@@ -1183,8 +1189,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) - { - struct netdev_private *np = netdev_priv(dev); - unsigned int entry; -+ unsigned int prev_tx; - u32 status; -- int i; -+ int i, j; - - /* - * be cautious here, wrapping the queue has weird semantics -@@ -1202,6 +1209,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) - } - #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ - -+ prev_tx = np->cur_tx; - entry = np->cur_tx % TX_RING_SIZE; - for (i = 0; i < skb_num_frags(skb); i++) { - int wrap_ring = 0; -@@ -1235,6 +1243,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) - skb_frag_size(this_frag), - PCI_DMA_TODEVICE); - } -+ if (pci_dma_mapping_error(np->pci_dev, -+ np->tx_info[entry].mapping)) { -+ dev->stats.tx_dropped++; -+ goto err_out; -+ } - - np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping); - np->tx_ring[entry].status = cpu_to_le32(status); -@@ -1269,8 +1282,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) - netif_stop_queue(dev); - - return NETDEV_TX_OK; --} - -+err_out: -+ entry = prev_tx % TX_RING_SIZE; -+ np->tx_info[entry].skb = NULL; -+ if (i > 0) { -+ pci_unmap_single(np->pci_dev, -+ np->tx_info[entry].mapping, -+ skb_first_frag_len(skb), -+ PCI_DMA_TODEVICE); -+ np->tx_info[entry].mapping = 0; -+ entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE; -+ for (j = 1; j < i; j++) { -+ pci_unmap_single(np->pci_dev, -+ np->tx_info[entry].mapping, -+ skb_frag_size( -+ &skb_shinfo(skb)->frags[j-1]), -+ PCI_DMA_TODEVICE); -+ entry++; -+ } -+ } -+ dev_kfree_skb_any(skb); -+ np->cur_tx = prev_tx; -+ return NETDEV_TX_OK; -+} - - /* The interrupt handler does all of the Rx thread work and cleans up - after the Tx thread. */ -@@ -1570,6 +1605,12 @@ static void refill_rx_ring(struct net_device *dev) - break; /* Better luck next round. */ - np->rx_info[entry].mapping = - pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); -+ if (pci_dma_mapping_error(np->pci_dev, -+ np->rx_info[entry].mapping)) { -+ dev_kfree_skb(skb); -+ np->rx_info[entry].skb = NULL; -+ break; -+ } - np->rx_ring[entry].rxaddr = - cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); - } -diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c -index 3e233d924cce..6a061f17a44f 100644 ---- a/drivers/net/ethernet/freescale/gianfar.c -+++ b/drivers/net/ethernet/freescale/gianfar.c -@@ -1999,8 +1999,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) - if (!rxb->page) - continue; - -- dma_unmap_single(rx_queue->dev, rxb->dma, -- PAGE_SIZE, DMA_FROM_DEVICE); -+ dma_unmap_page(rx_queue->dev, rxb->dma, -+ PAGE_SIZE, DMA_FROM_DEVICE); - __free_page(rxb->page); - - rxb->page = NULL; -diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c -index 08cef0dfb5db..2fa54b0b0679 100644 ---- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c -+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c -@@ -105,8 +105,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev, - struct hns_nic_ring_data *ring_data) - { - struct hns_nic_priv *priv = netdev_priv(ndev); -- struct device *dev = priv->dev; - struct hnae_ring *ring = ring_data->ring; -+ struct device *dev = ring_to_dev(ring); - struct netdev_queue *dev_queue; - struct skb_frag_struct *frag; - int buf_num; -diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c b/drivers/net/ethernet/mellanox/mlx4/catas.c -index 715de8affcc9..e203d0c4e5a3 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/catas.c -+++ b/drivers/net/ethernet/mellanox/mlx4/catas.c -@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev) - return -ETIMEDOUT; - } - --static int mlx4_comm_internal_err(u32 slave_read) -+int mlx4_comm_internal_err(u32 slave_read) - { - return (u32)COMM_CHAN_EVENT_INTERNAL_ERR == - (slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0; -diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c -index 0472941af820..1a134e08f010 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/intf.c -+++ b/drivers/net/ethernet/mellanox/mlx4/intf.c -@@ -218,6 +218,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev) - struct mlx4_interface *intf; - - mlx4_stop_catas_poll(dev); -+ if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION && -+ mlx4_is_slave(dev)) { -+ /* In mlx4_remove_one on a VF */ -+ u32 slave_read = -+ swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read)); -+ -+ if (mlx4_comm_internal_err(slave_read)) { -+ mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n", -+ __func__); -+ mlx4_enter_error_state(dev->persist); -+ } -+ } - mutex_lock(&intf_mutex); - - list_for_each_entry(intf, &intf_list, list) -diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h -index e1cf9036af22..f5fdbd53d052 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h -+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h -@@ -1205,6 +1205,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type); - void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); - - void mlx4_enter_error_state(struct mlx4_dev_persistent *persist); -+int mlx4_comm_internal_err(u32 slave_read); - - int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, - enum mlx4_port_type *type); -diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c -index 549ad2018e7f..1e61d4da72db 100644 ---- a/drivers/net/ethernet/renesas/ravb_main.c -+++ b/drivers/net/ethernet/renesas/ravb_main.c -@@ -171,6 +171,49 @@ static struct mdiobb_ops bb_ops = { - .get_mdio_data = ravb_get_mdio_data, - }; - -+/* Free TX skb function for AVB-IP */ -+static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only) -+{ -+ struct ravb_private *priv = netdev_priv(ndev); -+ struct net_device_stats *stats = &priv->stats[q]; -+ struct ravb_tx_desc *desc; -+ int free_num = 0; -+ int entry; -+ u32 size; -+ -+ for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) { -+ bool txed; -+ -+ entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] * -+ NUM_TX_DESC); -+ desc = &priv->tx_ring[q][entry]; -+ txed = desc->die_dt == DT_FEMPTY; -+ if (free_txed_only && !txed) -+ break; -+ /* Descriptor type must be checked before all other reads */ -+ dma_rmb(); -+ size = le16_to_cpu(desc->ds_tagl) & TX_DS; -+ /* Free the original skb. */ -+ if (priv->tx_skb[q][entry / NUM_TX_DESC]) { -+ dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), -+ size, DMA_TO_DEVICE); -+ /* Last packet descriptor? */ -+ if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) { -+ entry /= NUM_TX_DESC; -+ dev_kfree_skb_any(priv->tx_skb[q][entry]); -+ priv->tx_skb[q][entry] = NULL; -+ if (txed) -+ stats->tx_packets++; -+ } -+ free_num++; -+ } -+ if (txed) -+ stats->tx_bytes += size; -+ desc->die_dt = DT_EEMPTY; -+ } -+ return free_num; -+} -+ - /* Free skb's and DMA buffers for Ethernet AVB */ - static void ravb_ring_free(struct net_device *ndev, int q) - { -@@ -186,19 +229,21 @@ static void ravb_ring_free(struct net_device *ndev, int q) - kfree(priv->rx_skb[q]); - priv->rx_skb[q] = NULL; - -- /* Free TX skb ringbuffer */ -- if (priv->tx_skb[q]) { -- for (i = 0; i < priv->num_tx_ring[q]; i++) -- dev_kfree_skb(priv->tx_skb[q][i]); -- } -- kfree(priv->tx_skb[q]); -- priv->tx_skb[q] = NULL; -- - /* Free aligned TX buffers */ - kfree(priv->tx_align[q]); - priv->tx_align[q] = NULL; - - if (priv->rx_ring[q]) { -+ for (i = 0; i < priv->num_rx_ring[q]; i++) { -+ struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; -+ -+ if (!dma_mapping_error(ndev->dev.parent, -+ le32_to_cpu(desc->dptr))) -+ dma_unmap_single(ndev->dev.parent, -+ le32_to_cpu(desc->dptr), -+ PKT_BUF_SZ, -+ DMA_FROM_DEVICE); -+ } - ring_size = sizeof(struct ravb_ex_rx_desc) * - (priv->num_rx_ring[q] + 1); - dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q], -@@ -207,12 +252,20 @@ static void ravb_ring_free(struct net_device *ndev, int q) - } - - if (priv->tx_ring[q]) { -+ ravb_tx_free(ndev, q, false); -+ - ring_size = sizeof(struct ravb_tx_desc) * - (priv->num_tx_ring[q] * NUM_TX_DESC + 1); - dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q], - priv->tx_desc_dma[q]); - priv->tx_ring[q] = NULL; - } -+ -+ /* Free TX skb ringbuffer. -+ * SKBs are freed by ravb_tx_free() call above. -+ */ -+ kfree(priv->tx_skb[q]); -+ priv->tx_skb[q] = NULL; - } - - /* Format skb and descriptor buffer for Ethernet AVB */ -@@ -420,44 +473,6 @@ static int ravb_dmac_init(struct net_device *ndev) - return 0; - } - --/* Free TX skb function for AVB-IP */ --static int ravb_tx_free(struct net_device *ndev, int q) --{ -- struct ravb_private *priv = netdev_priv(ndev); -- struct net_device_stats *stats = &priv->stats[q]; -- struct ravb_tx_desc *desc; -- int free_num = 0; -- int entry; -- u32 size; -- -- for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) { -- entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] * -- NUM_TX_DESC); -- desc = &priv->tx_ring[q][entry]; -- if (desc->die_dt != DT_FEMPTY) -- break; -- /* Descriptor type must be checked before all other reads */ -- dma_rmb(); -- size = le16_to_cpu(desc->ds_tagl) & TX_DS; -- /* Free the original skb. */ -- if (priv->tx_skb[q][entry / NUM_TX_DESC]) { -- dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), -- size, DMA_TO_DEVICE); -- /* Last packet descriptor? */ -- if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) { -- entry /= NUM_TX_DESC; -- dev_kfree_skb_any(priv->tx_skb[q][entry]); -- priv->tx_skb[q][entry] = NULL; -- stats->tx_packets++; -- } -- free_num++; -- } -- stats->tx_bytes += size; -- desc->die_dt = DT_EEMPTY; -- } -- return free_num; --} -- - static void ravb_get_tx_tstamp(struct net_device *ndev) - { - struct ravb_private *priv = netdev_priv(ndev); -@@ -797,7 +812,7 @@ static int ravb_poll(struct napi_struct *napi, int budget) - spin_lock_irqsave(&priv->lock, flags); - /* Clear TX interrupt */ - ravb_write(ndev, ~mask, TIS); -- ravb_tx_free(ndev, q); -+ ravb_tx_free(ndev, q, true); - netif_wake_subqueue(ndev, q); - mmiowb(); - spin_unlock_irqrestore(&priv->lock, flags); -@@ -1393,7 +1408,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) - - priv->cur_tx[q] += NUM_TX_DESC; - if (priv->cur_tx[q] - priv->dirty_tx[q] > -- (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q)) -+ (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && -+ !ravb_tx_free(ndev, q, true)) - netif_stop_subqueue(ndev, q); - - exit: -diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c -index cf468c87ce57..4cb8b85cbf2c 100644 ---- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c -+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c -@@ -100,6 +100,14 @@ - /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */ - #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT) - -+#ifdef __BIG_ENDIAN -+#define xemaclite_readl ioread32be -+#define xemaclite_writel iowrite32be -+#else -+#define xemaclite_readl ioread32 -+#define xemaclite_writel iowrite32 -+#endif -+ - /** - * struct net_local - Our private per device data - * @ndev: instance of the network device -@@ -158,15 +166,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) - u32 reg_data; - - /* Enable the Tx interrupts for the first Buffer */ -- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); -- __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, -- drvdata->base_addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); -+ xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK, -+ drvdata->base_addr + XEL_TSR_OFFSET); - - /* Enable the Rx interrupts for the first buffer */ -- __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); -+ xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); - - /* Enable the Global Interrupt Enable */ -- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); -+ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); - } - - /** -@@ -181,17 +189,17 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata) - u32 reg_data; - - /* Disable the Global Interrupt Enable */ -- __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); -+ xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); - - /* Disable the Tx interrupts for the first buffer */ -- reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); -- __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), -- drvdata->base_addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET); -+ xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), -+ drvdata->base_addr + XEL_TSR_OFFSET); - - /* Disable the Rx interrupts for the first buffer */ -- reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET); -- __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), -- drvdata->base_addr + XEL_RSR_OFFSET); -+ reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET); -+ xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), -+ drvdata->base_addr + XEL_RSR_OFFSET); - } - - /** -@@ -323,7 +331,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, - byte_count = ETH_FRAME_LEN; - - /* Check if the expected buffer is available */ -- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); - if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | - XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { - -@@ -336,7 +344,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, - - addr = (void __iomem __force *)((u32 __force)addr ^ - XEL_BUFFER_OFFSET); -- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); - - if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | - XEL_TSR_XMIT_ACTIVE_MASK)) != 0) -@@ -347,16 +355,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, - /* Write the frame to the buffer */ - xemaclite_aligned_write(data, (u32 __force *) addr, byte_count); - -- __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK), -- addr + XEL_TPLR_OFFSET); -+ xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK), -+ addr + XEL_TPLR_OFFSET); - - /* Update the Tx Status Register to indicate that there is a - * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which - * is used by the interrupt handler to check whether a frame - * has been transmitted */ -- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); - reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK); -- __raw_writel(reg_data, addr + XEL_TSR_OFFSET); -+ xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET); - - return 0; - } -@@ -371,7 +379,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, - * - * Return: Total number of bytes received - */ --static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) -+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) - { - void __iomem *addr; - u16 length, proto_type; -@@ -381,7 +389,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) - addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use); - - /* Verify which buffer has valid data */ -- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); - - if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { - if (drvdata->rx_ping_pong != 0) -@@ -398,27 +406,28 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) - return 0; /* No data was available */ - - /* Verify that buffer has valid data */ -- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); - if ((reg_data & XEL_RSR_RECV_DONE_MASK) != - XEL_RSR_RECV_DONE_MASK) - return 0; /* No data was available */ - } - - /* Get the protocol type of the ethernet frame that arrived */ -- proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET + -+ proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET + - XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & - XEL_RPLR_LENGTH_MASK); - - /* Check if received ethernet frame is a raw ethernet frame - * or an IP packet or an ARP packet */ -- if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { -+ if (proto_type > ETH_DATA_LEN) { - - if (proto_type == ETH_P_IP) { -- length = ((ntohl(__raw_readl(addr + -+ length = ((ntohl(xemaclite_readl(addr + - XEL_HEADER_IP_LENGTH_OFFSET + - XEL_RXBUFF_OFFSET)) >> - XEL_HEADER_SHIFT) & - XEL_RPLR_LENGTH_MASK); -+ length = min_t(u16, length, ETH_DATA_LEN); - length += ETH_HLEN + ETH_FCS_LEN; - - } else if (proto_type == ETH_P_ARP) -@@ -431,14 +440,17 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) - /* Use the length in the frame, plus the header and trailer */ - length = proto_type + ETH_HLEN + ETH_FCS_LEN; - -+ if (WARN_ON(length > maxlen)) -+ length = maxlen; -+ - /* Read from the EmacLite device */ - xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET), - data, length); - - /* Acknowledge the frame */ -- reg_data = __raw_readl(addr + XEL_RSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET); - reg_data &= ~XEL_RSR_RECV_DONE_MASK; -- __raw_writel(reg_data, addr + XEL_RSR_OFFSET); -+ xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET); - - return length; - } -@@ -465,14 +477,14 @@ static void xemaclite_update_address(struct net_local *drvdata, - - xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN); - -- __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); -+ xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); - - /* Update the MAC address in the EmacLite */ -- reg_data = __raw_readl(addr + XEL_TSR_OFFSET); -- __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); -+ reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET); -+ xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); - - /* Wait for EmacLite to finish with the MAC address update */ -- while ((__raw_readl(addr + XEL_TSR_OFFSET) & -+ while ((xemaclite_readl(addr + XEL_TSR_OFFSET) & - XEL_TSR_PROG_MAC_ADDR) != 0) - ; - } -@@ -605,7 +617,7 @@ static void xemaclite_rx_handler(struct net_device *dev) - - skb_reserve(skb, 2); - -- len = xemaclite_recv_data(lp, (u8 *) skb->data); -+ len = xemaclite_recv_data(lp, (u8 *) skb->data, len); - - if (!len) { - dev->stats.rx_errors++; -@@ -642,32 +654,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id) - u32 tx_status; - - /* Check if there is Rx Data available */ -- if ((__raw_readl(base_addr + XEL_RSR_OFFSET) & -+ if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) & - XEL_RSR_RECV_DONE_MASK) || -- (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) -+ (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) - & XEL_RSR_RECV_DONE_MASK)) - - xemaclite_rx_handler(dev); - - /* Check if the Transmission for the first buffer is completed */ -- tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET); -+ tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET); - if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && - (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { - - tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; -- __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET); -+ xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET); - - tx_complete = true; - } - - /* Check if the Transmission for the second buffer is completed */ -- tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); -+ tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); - if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && - (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { - - tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; -- __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + -- XEL_TSR_OFFSET); -+ xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + -+ XEL_TSR_OFFSET); - - tx_complete = true; - } -@@ -700,7 +712,7 @@ static int xemaclite_mdio_wait(struct net_local *lp) - /* wait for the MDIO interface to not be busy or timeout - after some time. - */ -- while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & -+ while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & - XEL_MDIOCTRL_MDIOSTS_MASK) { - if (time_before_eq(end, jiffies)) { - WARN_ON(1); -@@ -736,17 +748,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg) - * MDIO Address register. Set the Status bit in the MDIO Control - * register to start a MDIO read transaction. - */ -- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); -- __raw_writel(XEL_MDIOADDR_OP_MASK | -- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), -- lp->base_addr + XEL_MDIOADDR_OFFSET); -- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, -- lp->base_addr + XEL_MDIOCTRL_OFFSET); -+ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); -+ xemaclite_writel(XEL_MDIOADDR_OP_MASK | -+ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), -+ lp->base_addr + XEL_MDIOADDR_OFFSET); -+ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, -+ lp->base_addr + XEL_MDIOCTRL_OFFSET); - - if (xemaclite_mdio_wait(lp)) - return -ETIMEDOUT; - -- rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET); -+ rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET); - - dev_dbg(&lp->ndev->dev, - "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n", -@@ -783,13 +795,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, - * Data register. Finally, set the Status bit in the MDIO Control - * register to start a MDIO write transaction. - */ -- ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); -- __raw_writel(~XEL_MDIOADDR_OP_MASK & -- ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), -- lp->base_addr + XEL_MDIOADDR_OFFSET); -- __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); -- __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, -- lp->base_addr + XEL_MDIOCTRL_OFFSET); -+ ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); -+ xemaclite_writel(~XEL_MDIOADDR_OP_MASK & -+ ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), -+ lp->base_addr + XEL_MDIOADDR_OFFSET); -+ xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); -+ xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, -+ lp->base_addr + XEL_MDIOCTRL_OFFSET); - - return 0; - } -@@ -836,8 +848,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) - /* Enable the MDIO bus by asserting the enable bit in MDIO Control - * register. - */ -- __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, -- lp->base_addr + XEL_MDIOCTRL_OFFSET); -+ xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK, -+ lp->base_addr + XEL_MDIOCTRL_OFFSET); - - bus = mdiobus_alloc(); - if (!bus) { -@@ -1141,8 +1153,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) - dev_warn(dev, "No MAC address found\n"); - - /* Clear the Tx CSR's in case this is a restart */ -- __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET); -- __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); -+ xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET); -+ xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); - - /* Set the MAC address in the EmacLite device */ - xemaclite_update_address(lp, ndev->dev_addr); -diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c -index 85828f153445..0758d0816840 100644 ---- a/drivers/net/hamradio/mkiss.c -+++ b/drivers/net/hamradio/mkiss.c -@@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev) - { - /* Finish setting up the DEVICE info. */ - dev->mtu = AX_MTU; -- dev->hard_header_len = 0; -- dev->addr_len = 0; -+ dev->hard_header_len = AX25_MAX_HEADER_LEN; -+ dev->addr_len = AX25_ADDR_LEN; - dev->type = ARPHRD_AX25; - dev->tx_queue_len = 10; - dev->header_ops = &ax25_header_ops; -diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c -index fbb1867ff25c..1c27e6fb99f9 100644 ---- a/drivers/net/usb/r8152.c -+++ b/drivers/net/usb/r8152.c -@@ -1851,6 +1851,9 @@ static int r8152_poll(struct napi_struct *napi, int budget) - napi_complete(napi); - if (!list_empty(&tp->rx_done)) - napi_schedule(napi); -+ else if (!skb_queue_empty(&tp->tx_queue) && -+ !list_empty(&tp->tx_free)) -+ napi_schedule(napi); - } - - return work_done; -@@ -2990,10 +2993,13 @@ static void set_carrier(struct r8152 *tp) - if (!netif_carrier_ok(netdev)) { - tp->rtl_ops.enable(tp); - set_bit(RTL8152_SET_RX_MODE, &tp->flags); -+ netif_stop_queue(netdev); - napi_disable(&tp->napi); - netif_carrier_on(netdev); - rtl_start_rx(tp); - napi_enable(&tp->napi); -+ netif_wake_queue(netdev); -+ netif_info(tp, link, netdev, "carrier on\n"); - } - } else { - if (netif_carrier_ok(netdev)) { -@@ -3001,6 +3007,7 @@ static void set_carrier(struct r8152 *tp) - napi_disable(&tp->napi); - tp->rtl_ops.disable(tp); - napi_enable(&tp->napi); -+ netif_info(tp, link, netdev, "carrier off\n"); - } - } - } -@@ -3385,12 +3392,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf) - if (!netif_running(netdev)) - return 0; - -+ netif_stop_queue(netdev); - napi_disable(&tp->napi); - clear_bit(WORK_ENABLE, &tp->flags); - usb_kill_urb(tp->intr_urb); - cancel_delayed_work_sync(&tp->schedule); - if (netif_carrier_ok(netdev)) { -- netif_stop_queue(netdev); - mutex_lock(&tp->control); - tp->rtl_ops.disable(tp); - mutex_unlock(&tp->control); -@@ -3415,12 +3422,14 @@ static int rtl8152_post_reset(struct usb_interface *intf) - if (netif_carrier_ok(netdev)) { - mutex_lock(&tp->control); - tp->rtl_ops.enable(tp); -+ rtl_start_rx(tp); - rtl8152_set_rx_mode(netdev); - mutex_unlock(&tp->control); -- netif_wake_queue(netdev); - } - - napi_enable(&tp->napi); -+ netif_wake_queue(netdev); -+ usb_submit_urb(tp->intr_urb, GFP_KERNEL); - - return 0; - } -diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c -index a251588762ec..0b5a84c9022c 100644 ---- a/drivers/net/usb/sierra_net.c -+++ b/drivers/net/usb/sierra_net.c -@@ -73,8 +73,6 @@ static atomic_t iface_counter = ATOMIC_INIT(0); - /* Private data structure */ - struct sierra_net_data { - -- u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */ -- - u16 link_up; /* air link up or down */ - u8 tx_hdr_template[4]; /* part of HIP hdr for tx'd packets */ - -@@ -122,6 +120,7 @@ struct param { - - /* LSI Protocol types */ - #define SIERRA_NET_PROTOCOL_UMTS 0x01 -+#define SIERRA_NET_PROTOCOL_UMTS_DS 0x04 - /* LSI Coverage */ - #define SIERRA_NET_COVERAGE_NONE 0x00 - #define SIERRA_NET_COVERAGE_NOPACKET 0x01 -@@ -129,7 +128,8 @@ struct param { - /* LSI Session */ - #define SIERRA_NET_SESSION_IDLE 0x00 - /* LSI Link types */ --#define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00 -+#define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00 -+#define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02 - - struct lsi_umts { - u8 protocol; -@@ -137,9 +137,14 @@ struct lsi_umts { - __be16 length; - /* eventually use a union for the rest - assume umts for now */ - u8 coverage; -- u8 unused2[41]; -+ u8 network_len; /* network name len */ -+ u8 network[40]; /* network name (UCS2, bigendian) */ - u8 session_state; - u8 unused3[33]; -+} __packed; -+ -+struct lsi_umts_single { -+ struct lsi_umts lsi; - u8 link_type; - u8 pdp_addr_len; /* NW-supplied PDP address len */ - u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */ -@@ -158,10 +163,31 @@ struct lsi_umts { - u8 reserved[8]; - } __packed; - -+struct lsi_umts_dual { -+ struct lsi_umts lsi; -+ u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */ -+ u8 pdp_addr4[4]; /* NW-supplied PDP IPv4 address (bigendian)) */ -+ u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */ -+ u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */ -+ u8 unused4[23]; -+ u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */ -+ u8 dns1_addr4[4]; /* NW-supplied 1st DNS v4 address */ -+ u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */ -+ u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/ -+ u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */ -+ u8 dns2_addr4[4]; /* NW-supplied 2nd DNS v4 address */ -+ u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */ -+ u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/ -+ u8 unused5[68]; -+} __packed; -+ - #define SIERRA_NET_LSI_COMMON_LEN 4 --#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts)) -+#define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single)) - #define SIERRA_NET_LSI_UMTS_STATUS_LEN \ - (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN) -+#define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual)) -+#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \ -+ (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN) - - /* Forward definitions */ - static void sierra_sync_timer(unsigned long syncdata); -@@ -191,10 +217,11 @@ static inline void sierra_net_set_private(struct usbnet *dev, - dev->data[0] = (unsigned long)priv; - } - --/* is packet IPv4 */ -+/* is packet IPv4/IPv6 */ - static inline int is_ip(struct sk_buff *skb) - { -- return skb->protocol == cpu_to_be16(ETH_P_IP); -+ return skb->protocol == cpu_to_be16(ETH_P_IP) || -+ skb->protocol == cpu_to_be16(ETH_P_IPV6); - } - - /* -@@ -350,49 +377,54 @@ static inline int sierra_net_is_valid_addrlen(u8 len) - static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen) - { - struct lsi_umts *lsi = (struct lsi_umts *)data; -+ u32 expected_length; - -- if (datalen < sizeof(struct lsi_umts)) { -- netdev_err(dev->net, "%s: Data length %d, exp %Zu\n", -- __func__, datalen, -- sizeof(struct lsi_umts)); -+ if (datalen < sizeof(struct lsi_umts_single)) { -+ netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n", -+ __func__, datalen, sizeof(struct lsi_umts_single)); - return -1; - } - -- if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) { -- netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", -- __func__, be16_to_cpu(lsi->length), -- (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN); -- return -1; -+ /* Validate the session state */ -+ if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { -+ netdev_err(dev->net, "Session idle, 0x%02x\n", -+ lsi->session_state); -+ return 0; - } - - /* Validate the protocol - only support UMTS for now */ -- if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) { -+ if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) { -+ struct lsi_umts_single *single = (struct lsi_umts_single *)lsi; -+ -+ /* Validate the link type */ -+ if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 && -+ single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) { -+ netdev_err(dev->net, "Link type unsupported: 0x%02x\n", -+ single->link_type); -+ return -1; -+ } -+ expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN; -+ } else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) { -+ expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN; -+ } else { - netdev_err(dev->net, "Protocol unsupported, 0x%02x\n", -- lsi->protocol); -+ lsi->protocol); - return -1; - } - -- /* Validate the link type */ -- if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) { -- netdev_err(dev->net, "Link type unsupported: 0x%02x\n", -- lsi->link_type); -+ if (be16_to_cpu(lsi->length) != expected_length) { -+ netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n", -+ __func__, be16_to_cpu(lsi->length), expected_length); - return -1; - } - - /* Validate the coverage */ -- if (lsi->coverage == SIERRA_NET_COVERAGE_NONE -- || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { -+ if (lsi->coverage == SIERRA_NET_COVERAGE_NONE || -+ lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) { - netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage); - return 0; - } - -- /* Validate the session state */ -- if (lsi->session_state == SIERRA_NET_SESSION_IDLE) { -- netdev_err(dev->net, "Session idle, 0x%02x\n", -- lsi->session_state); -- return 0; -- } -- - /* Set link_sense true */ - return 1; - } -@@ -662,7 +694,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) - u8 numendpoints; - u16 fwattr = 0; - int status; -- struct ethhdr *eth; - struct sierra_net_data *priv; - static const u8 sync_tmplate[sizeof(priv->sync_msg)] = { - 0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00}; -@@ -700,11 +731,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) - dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter); - dev->net->dev_addr[ETH_ALEN-1] = ifacenum; - -- /* we will have to manufacture ethernet headers, prepare template */ -- eth = (struct ethhdr *)priv->ethr_hdr_tmpl; -- memcpy(ð->h_dest, dev->net->dev_addr, ETH_ALEN); -- eth->h_proto = cpu_to_be16(ETH_P_IP); -- - /* prepare shutdown message template */ - memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg)); - /* set context index initially to 0 - prepares tx hdr template */ -@@ -833,9 +859,14 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb) - - skb_pull(skb, hh.hdrlen); - -- /* We are going to accept this packet, prepare it */ -- memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl, -- ETH_HLEN); -+ /* We are going to accept this packet, prepare it. -+ * In case protocol is IPv6, keep it, otherwise force IPv4. -+ */ -+ skb_reset_mac_header(skb); -+ if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6)) -+ eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP); -+ eth_zero_addr(eth_hdr(skb)->h_source); -+ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); - - /* Last packet in batch handled by usbnet */ - if (hh.payload_len.word == skb->len) -diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c -index 6e3a60c78873..50f3bb0dd1f1 100644 ---- a/drivers/parport/parport_gsc.c -+++ b/drivers/parport/parport_gsc.c -@@ -293,7 +293,7 @@ struct parport *parport_gsc_probe_port(unsigned long base, - p->irq = PARPORT_IRQ_NONE; - } - if (p->irq != PARPORT_IRQ_NONE) { -- printk(", irq %d", p->irq); -+ pr_cont(", irq %d", p->irq); - - if (p->dma == PARPORT_DMA_AUTO) { - p->dma = PARPORT_DMA_NONE; -@@ -303,8 +303,8 @@ struct parport *parport_gsc_probe_port(unsigned long base, - is mandatory (see above) */ - p->dma = PARPORT_DMA_NONE; - -- printk(" ["); --#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}} -+ pr_cont(" ["); -+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}} - { - int f = 0; - printmode(PCSPP); -@@ -315,7 +315,7 @@ struct parport *parport_gsc_probe_port(unsigned long base, - // printmode(DMA); - } - #undef printmode -- printk("]\n"); -+ pr_cont("]\n"); - - if (p->irq != PARPORT_IRQ_NONE) { - if (request_irq (p->irq, parport_irq_handler, -diff --git a/drivers/pinctrl/berlin/berlin-bg4ct.c b/drivers/pinctrl/berlin/berlin-bg4ct.c -index 09172043d589..c617ec49e9ed 100644 ---- a/drivers/pinctrl/berlin/berlin-bg4ct.c -+++ b/drivers/pinctrl/berlin/berlin-bg4ct.c -@@ -217,7 +217,7 @@ static const struct berlin_desc_group berlin4ct_soc_pinctrl_groups[] = { - BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15, - BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */ - BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */ -- BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */ -+ BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */ - BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18, - BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */ - BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */ -diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -index 79bf13f5c0d1..7a8ceb961bb6 100644 ---- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c -@@ -1185,8 +1185,7 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, - struct cb_desc *cb_desc, struct sk_buff *skb) - { - struct r8192_priv *priv = rtllib_priv(dev); -- dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, -- PCI_DMA_TODEVICE); -+ dma_addr_t mapping; - struct tx_fwinfo_8190pci *pTxFwInfo = NULL; - - pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data; -@@ -1197,8 +1196,6 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, - pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT, - pTxFwInfo->TxRate, cb_desc); - -- if (pci_dma_mapping_error(priv->pdev, mapping)) -- netdev_err(dev, "%s(): DMA Mapping error\n", __func__); - if (cb_desc->bAMPDUEnable) { - pTxFwInfo->AllowAggregation = 1; - pTxFwInfo->RxMF = cb_desc->ampdu_factor; -@@ -1233,6 +1230,14 @@ void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, - } - - memset((u8 *)pdesc, 0, 12); -+ -+ mapping = pci_map_single(priv->pdev, skb->data, skb->len, -+ PCI_DMA_TODEVICE); -+ if (pci_dma_mapping_error(priv->pdev, mapping)) { -+ netdev_err(dev, "%s(): DMA Mapping error\n", __func__); -+ return; -+ } -+ - pdesc->LINIP = 0; - pdesc->CmdInit = 1; - pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; -diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c -index 156bc18eac69..53a827c6d8b1 100644 ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -412,6 +412,9 @@ cifs_reconnect(struct TCP_Server_Info *server) - } - } while (server->tcpStatus == CifsNeedReconnect); - -+ if (server->tcpStatus == CifsNeedNegotiate) -+ mod_delayed_work(cifsiod_wq, &server->echo, 0); -+ - return rc; - } - -@@ -421,18 +424,27 @@ cifs_echo_request(struct work_struct *work) - int rc; - struct TCP_Server_Info *server = container_of(work, - struct TCP_Server_Info, echo.work); -+ unsigned long echo_interval; -+ -+ /* -+ * If we need to renegotiate, set echo interval to zero to -+ * immediately call echo service where we can renegotiate. -+ */ -+ if (server->tcpStatus == CifsNeedNegotiate) -+ echo_interval = 0; -+ else -+ echo_interval = SMB_ECHO_INTERVAL; - - /* -- * We cannot send an echo if it is disabled or until the -- * NEGOTIATE_PROTOCOL request is done, which is indicated by -- * server->ops->need_neg() == true. Also, no need to ping if -- * we got a response recently. -+ * We cannot send an echo if it is disabled. -+ * Also, no need to ping if we got a response recently. - */ - - if (server->tcpStatus == CifsNeedReconnect || -- server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew || -+ server->tcpStatus == CifsExiting || -+ server->tcpStatus == CifsNew || - (server->ops->can_echo && !server->ops->can_echo(server)) || -- time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) -+ time_before(jiffies, server->lstrp + echo_interval - HZ)) - goto requeue_echo; - - rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS; -diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c -index 4304072161aa..40d61077bead 100644 ---- a/fs/fscache/cookie.c -+++ b/fs/fscache/cookie.c -@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) - hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) { - if (invalidate) - set_bit(FSCACHE_OBJECT_RETIRED, &object->flags); -+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); - fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL); - } - } else { -@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) - wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t, - TASK_UNINTERRUPTIBLE); - -+ /* Make sure any pending writes are cancelled. */ -+ if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) -+ fscache_invalidate_writes(cookie); -+ - /* Reset the cookie state if it wasn't relinquished */ - if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) { - atomic_inc(&cookie->n_active); -diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c -index 9b28649df3a1..a8aa00be4444 100644 ---- a/fs/fscache/netfs.c -+++ b/fs/fscache/netfs.c -@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs) - cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; - - spin_lock_init(&cookie->lock); -+ spin_lock_init(&cookie->stores_lock); - INIT_HLIST_HEAD(&cookie->backing_objects); - - /* check the netfs type is not already present */ -diff --git a/fs/fscache/object.c b/fs/fscache/object.c -index 9e792e30f4db..7a182c87f378 100644 ---- a/fs/fscache/object.c -+++ b/fs/fscache/object.c -@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object - static const struct fscache_state *fscache_object_available(struct fscache_object *, int); - static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int); - static const struct fscache_state *fscache_update_object(struct fscache_object *, int); -+static const struct fscache_state *fscache_object_dead(struct fscache_object *, int); - - #define __STATE_NAME(n) fscache_osm_##n - #define STATE(n) (&__STATE_NAME(n)) -@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE, "LCFL", fscache_lookup_failure); - static WORK_STATE(KILL_OBJECT, "KILL", fscache_kill_object); - static WORK_STATE(KILL_DEPENDENTS, "KDEP", fscache_kill_dependents); - static WORK_STATE(DROP_OBJECT, "DROP", fscache_drop_object); --static WORK_STATE(OBJECT_DEAD, "DEAD", (void*)2UL); -+static WORK_STATE(OBJECT_DEAD, "DEAD", fscache_object_dead); - - static WAIT_STATE(WAIT_FOR_INIT, "?INI", - TRANSIT_TO(INIT_OBJECT, 1 << FSCACHE_OBJECT_EV_NEW_CHILD)); -@@ -229,6 +230,10 @@ execute_work_state: - event = -1; - if (new_state == NO_TRANSIT) { - _debug("{OBJ%x} %s notrans", object->debug_id, state->name); -+ if (unlikely(state == STATE(OBJECT_DEAD))) { -+ _leave(" [dead]"); -+ return; -+ } - fscache_enqueue_object(object); - event_mask = object->oob_event_mask; - goto unmask_events; -@@ -239,7 +244,7 @@ execute_work_state: - object->state = state = new_state; - - if (state->work) { -- if (unlikely(state->work == ((void *)2UL))) { -+ if (unlikely(state == STATE(OBJECT_DEAD))) { - _leave(" [dead]"); - return; - } -@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob - fscache_mark_object_dead(object); - object->oob_event_mask = 0; - -+ if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) { -+ /* Reject any new read/write ops and abort any that are pending. */ -+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); -+ fscache_cancel_all_ops(object); -+ } -+ - if (list_empty(&object->dependents) && - object->n_ops == 0 && - object->n_children == 0) -@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object, - } - } - EXPORT_SYMBOL(fscache_object_mark_killed); -+ -+/* -+ * The object is dead. We can get here if an object gets queued by an event -+ * that would lead to its death (such as EV_KILL) when the dispatcher is -+ * already running (and so can be requeued) but hasn't yet cleared the event -+ * mask. -+ */ -+static const struct fscache_state *fscache_object_dead(struct fscache_object *object, -+ int event) -+{ -+ if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD, -+ &object->flags)) -+ return NO_TRANSIT; -+ -+ WARN(true, "FS-Cache object redispatched after death"); -+ return NO_TRANSIT; -+} -diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c -index 82dc3035ea45..e8d1d6c5000c 100644 ---- a/fs/nfs/nfs4state.c -+++ b/fs/nfs/nfs4state.c -@@ -1072,6 +1072,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) - case -NFS4ERR_BADXDR: - case -NFS4ERR_RESOURCE: - case -NFS4ERR_NOFILEHANDLE: -+ case -NFS4ERR_MOVED: - /* Non-seqid mutating errors */ - return; - }; -diff --git a/fs/proc/base.c b/fs/proc/base.c -index d2b8c754f627..dd732400578e 100644 ---- a/fs/proc/base.c -+++ b/fs/proc/base.c -@@ -3058,6 +3058,8 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx) - iter.tgid += 1, iter = next_tgid(ns, iter)) { - char name[PROC_NUMBUF]; - int len; -+ -+ cond_resched(); - if (!has_pid_permissions(ns, iter.task, 2)) - continue; - -diff --git a/fs/romfs/super.c b/fs/romfs/super.c -index 268733cda397..5f4f1882dc7d 100644 ---- a/fs/romfs/super.c -+++ b/fs/romfs/super.c -@@ -74,6 +74,7 @@ - #include - #include - #include -+#include - #include "internal.h" - - static struct kmem_cache *romfs_inode_cachep; -@@ -415,7 +416,22 @@ static void romfs_destroy_inode(struct inode *inode) - static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf) - { - struct super_block *sb = dentry->d_sb; -- u64 id = huge_encode_dev(sb->s_bdev->bd_dev); -+ u64 id = 0; -+ -+ /* When calling huge_encode_dev(), -+ * use sb->s_bdev->bd_dev when, -+ * - CONFIG_ROMFS_ON_BLOCK defined -+ * use sb->s_dev when, -+ * - CONFIG_ROMFS_ON_BLOCK undefined and -+ * - CONFIG_ROMFS_ON_MTD defined -+ * leave id as 0 when, -+ * - CONFIG_ROMFS_ON_BLOCK undefined and -+ * - CONFIG_ROMFS_ON_MTD undefined -+ */ -+ if (sb->s_bdev) -+ id = huge_encode_dev(sb->s_bdev->bd_dev); -+ else if (sb->s_dev) -+ id = huge_encode_dev(sb->s_dev); - - buf->f_type = ROMFS_MAGIC; - buf->f_namelen = ROMFS_MAXFN; -@@ -488,6 +504,11 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) - sb->s_flags |= MS_RDONLY | MS_NOATIME; - sb->s_op = &romfs_super_ops; - -+#ifdef CONFIG_ROMFS_ON_MTD -+ /* Use same dev ID from the underlying mtdblock device */ -+ if (sb->s_mtd) -+ sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index); -+#endif - /* read the image superblock and check it */ - rsb = kmalloc(512, GFP_KERNEL); - if (!rsb) -diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h -index 604e1526cd00..eb19bf2b2a81 100644 ---- a/include/linux/fscache-cache.h -+++ b/include/linux/fscache-cache.h -@@ -360,6 +360,7 @@ struct fscache_object { - #define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ - #define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */ - #define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */ -+#define FSCACHE_OBJECT_RUN_AFTER_DEAD 8 /* T if object has been dispatched after death */ - - struct list_head cache_link; /* link in cache->object_list */ - struct hlist_node cookie_link; /* link in cookie->backing_objects */ -diff --git a/include/linux/log2.h b/include/linux/log2.h -index f38fae23bdac..c373295f359f 100644 ---- a/include/linux/log2.h -+++ b/include/linux/log2.h -@@ -194,6 +194,17 @@ unsigned long __rounddown_pow_of_two(unsigned long n) - * ... and so on. - */ - --#define order_base_2(n) ilog2(roundup_pow_of_two(n)) -+static inline __attribute_const__ -+int __order_base_2(unsigned long n) -+{ -+ return n > 1 ? ilog2(n - 1) + 1 : 0; -+} - -+#define order_base_2(n) \ -+( \ -+ __builtin_constant_p(n) ? ( \ -+ ((n) == 0 || (n) == 1) ? 0 : \ -+ ilog2((n) - 1) + 1) : \ -+ __order_base_2(n) \ -+) - #endif /* _LINUX_LOG2_H */ -diff --git a/include/net/ipv6.h b/include/net/ipv6.h -index ad1d6039185d..7a8066b90289 100644 ---- a/include/net/ipv6.h -+++ b/include/net/ipv6.h -@@ -744,6 +744,11 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb, - { - u32 hash; - -+ /* @flowlabel may include more than a flow label, eg, the traffic class. -+ * Here we want only the flow label value. -+ */ -+ flowlabel &= IPV6_FLOWLABEL_MASK; -+ - if (flowlabel || - net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF || - (!autolabel && -diff --git a/mm/kasan/report.c b/mm/kasan/report.c -index 12f222d0224b..b4e31f78ae69 100644 ---- a/mm/kasan/report.c -+++ b/mm/kasan/report.c -@@ -13,6 +13,7 @@ - * - */ - -+#include - #include - #include - #include -@@ -251,6 +252,8 @@ void kasan_report(unsigned long addr, size_t size, - if (likely(!kasan_report_enabled())) - return; - -+ disable_trace_on_warning(); -+ - info.access_addr = (void *)addr; - info.access_size = size; - info.is_write = is_write; -diff --git a/net/core/ethtool.c b/net/core/ethtool.c -index 29edf74846fc..b6bca625b0d2 100644 ---- a/net/core/ethtool.c -+++ b/net/core/ethtool.c -@@ -886,9 +886,12 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) - if (regs.len > reglen) - regs.len = reglen; - -- regbuf = vzalloc(reglen); -- if (reglen && !regbuf) -- return -ENOMEM; -+ regbuf = NULL; -+ if (reglen) { -+ regbuf = vzalloc(reglen); -+ if (!regbuf) -+ return -ENOMEM; -+ } - - ops->get_regs(dev, ®s, regbuf); - -diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c -index 59b3e0e8fd51..711b4dfa17c3 100644 ---- a/net/ipv4/arp.c -+++ b/net/ipv4/arp.c -@@ -1250,7 +1250,7 @@ void __init arp_init(void) - /* - * ax25 -> ASCII conversion - */ --static char *ax2asc2(ax25_address *a, char *buf) -+static void ax2asc2(ax25_address *a, char *buf) - { - char c, *s; - int n; -@@ -1272,10 +1272,10 @@ static char *ax2asc2(ax25_address *a, char *buf) - *s++ = n + '0'; - *s++ = '\0'; - -- if (*buf == '\0' || *buf == '-') -- return "*"; -- -- return buf; -+ if (*buf == '\0' || *buf == '-') { -+ buf[0] = '*'; -+ buf[1] = '\0'; -+ } - } - #endif /* CONFIG_AX25 */ - -@@ -1309,7 +1309,7 @@ static void arp_format_neigh_entry(struct seq_file *seq, - } - #endif - sprintf(tbuf, "%pI4", n->primary_key); -- seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", -+ seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s * %s\n", - tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); - read_unlock(&n->lock); - } -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 7090fef372cc..8cf3fc7c2932 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -3211,9 +3211,15 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, - } - - if (idev) { -- if (idev->if_flags & IF_READY) -- /* device is already configured. */ -+ if (idev->if_flags & IF_READY) { -+ /* device is already configured - -+ * but resend MLD reports, we might -+ * have roamed and need to update -+ * multicast snooping switches -+ */ -+ ipv6_mc_up(idev); - break; -+ } - idev->if_flags |= IF_READY; - } - -diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c -index 428162155280..cae37bfd12ab 100644 ---- a/net/ipv6/datagram.c -+++ b/net/ipv6/datagram.c -@@ -76,18 +76,22 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a - } - } - -- addr_type = ipv6_addr_type(&usin->sin6_addr); -- -- if (addr_type == IPV6_ADDR_ANY) { -+ if (ipv6_addr_any(&usin->sin6_addr)) { - /* - * connect to self - */ -- usin->sin6_addr.s6_addr[15] = 0x01; -+ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) -+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), -+ &usin->sin6_addr); -+ else -+ usin->sin6_addr = in6addr_loopback; - } - -+ addr_type = ipv6_addr_type(&usin->sin6_addr); -+ - daddr = &usin->sin6_addr; - -- if (addr_type == IPV6_ADDR_MAPPED) { -+ if (addr_type & IPV6_ADDR_MAPPED) { - struct sockaddr_in sin; - - if (__ipv6_only_sock(sk)) { -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 1db17efe36c1..19c0d67ce8c4 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1004,6 +1004,9 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, - } - } - #endif -+ if (ipv6_addr_v4mapped(&fl6->saddr) && -+ !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) -+ return -EAFNOSUPPORT; - - return 0; - -diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c -index 8e958fde6e4b..59c908ff251a 100644 ---- a/net/ipv6/tcp_ipv6.c -+++ b/net/ipv6/tcp_ipv6.c -@@ -149,8 +149,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, - * connect() to INADDR_ANY means loopback (BSD'ism). - */ - -- if (ipv6_addr_any(&usin->sin6_addr)) -- usin->sin6_addr.s6_addr[15] = 0x1; -+ if (ipv6_addr_any(&usin->sin6_addr)) { -+ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)) -+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), -+ &usin->sin6_addr); -+ else -+ usin->sin6_addr = in6addr_loopback; -+ } - - addr_type = ipv6_addr_type(&usin->sin6_addr); - -@@ -189,7 +194,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, - * TCP over IPv4 - */ - -- if (addr_type == IPV6_ADDR_MAPPED) { -+ if (addr_type & IPV6_ADDR_MAPPED) { - u32 exthdrlen = icsk->icsk_ext_hdr_len; - struct sockaddr_in sin; - -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index dfa85e7264df..6fd4af3b5b79 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -1136,6 +1136,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) - if (addr_len < SIN6_LEN_RFC2133) - return -EINVAL; - daddr = &sin6->sin6_addr; -+ if (ipv6_addr_any(daddr) && -+ ipv6_addr_v4mapped(&np->saddr)) -+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), -+ daddr); - break; - case AF_INET: - goto do_udp_sendmsg; -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index c96d666cef29..956141b71619 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -235,8 +235,12 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, - sctp_assoc_t id) - { - struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; -- struct sctp_transport *transport; -+ struct sctp_af *af = sctp_get_af_specific(addr->ss_family); - union sctp_addr *laddr = (union sctp_addr *)addr; -+ struct sctp_transport *transport; -+ -+ if (sctp_verify_addr(sk, laddr, af->sockaddr_len)) -+ return NULL; - - addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, - laddr, -diff --git a/net/tipc/server.c b/net/tipc/server.c -index 922e04a43396..50f5b0ca7b3c 100644 ---- a/net/tipc/server.c -+++ b/net/tipc/server.c -@@ -452,6 +452,11 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, - if (!con) - return -EINVAL; - -+ if (!test_bit(CF_CONNECTED, &con->flags)) { -+ conn_put(con); -+ return 0; -+ } -+ - e = tipc_alloc_entry(data, len); - if (!e) { - conn_put(con); -@@ -465,12 +470,8 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid, - list_add_tail(&e->list, &con->outqueue); - spin_unlock_bh(&con->outqueue_lock); - -- if (test_bit(CF_CONNECTED, &con->flags)) { -- if (!queue_work(s->send_wq, &con->swork)) -- conn_put(con); -- } else { -+ if (!queue_work(s->send_wq, &con->swork)) - conn_put(con); -- } - return 0; - } - -@@ -494,7 +495,7 @@ static void tipc_send_to_sock(struct tipc_conn *con) - int ret; - - spin_lock_bh(&con->outqueue_lock); -- while (1) { -+ while (test_bit(CF_CONNECTED, &con->flags)) { - e = list_entry(con->outqueue.next, struct outqueue_entry, - list); - if ((struct list_head *) e == &con->outqueue) diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.73-74.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.73-74.patch deleted file mode 100644 index 4c15d4deb..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.73-74.patch +++ /dev/null @@ -1,1488 +0,0 @@ -diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt -index ca64ca566099..7c77d7edb851 100644 ---- a/Documentation/kernel-parameters.txt -+++ b/Documentation/kernel-parameters.txt -@@ -3580,6 +3580,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. - spia_pedr= - spia_peddr= - -+ stack_guard_gap= [MM] -+ override the default stack gap protection. The value -+ is in page units and it defines how many pages prior -+ to (for stacks growing down) resp. after (for stacks -+ growing up) the main stack are reserved for no other -+ mapping. Default value is 256 pages. -+ - stacktrace [FTRACE] - Enabled the stack tracer on boot up. - -diff --git a/Makefile b/Makefile -index ba5a70b6e32c..1f75507acbf4 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 73 -+SUBLEVEL = 74 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c -index 2e06d56e987b..cf4ae6958240 100644 ---- a/arch/arc/mm/mmap.c -+++ b/arch/arc/mm/mmap.c -@@ -64,7 +64,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c -index 407dc786583a..c469c0665752 100644 ---- a/arch/arm/mm/mmap.c -+++ b/arch/arm/mm/mmap.c -@@ -89,7 +89,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -@@ -140,7 +140,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c -index 836f14707a62..efa59f1f8022 100644 ---- a/arch/frv/mm/elf-fdpic.c -+++ b/arch/frv/mm/elf-fdpic.c -@@ -74,7 +74,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi - addr = PAGE_ALIGN(addr); - vma = find_vma(current->mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - goto success; - } - -diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c -index d8f9b357b222..e9fed8ca9b42 100644 ---- a/arch/mips/kernel/branch.c -+++ b/arch/mips/kernel/branch.c -@@ -816,8 +816,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - break; - } - /* Compact branch: BNEZC || JIALC */ -- if (insn.i_format.rs) -+ if (!insn.i_format.rs) { -+ /* JIALC: set $31/ra */ - regs->regs[31] = epc + 4; -+ } - regs->cp0_epc += 8; - break; - #endif -diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c -index 5c81fdd032c3..025cb31aa0a2 100644 ---- a/arch/mips/mm/mmap.c -+++ b/arch/mips/mm/mmap.c -@@ -92,7 +92,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c -index 5aba01ac457f..4dda73c44fee 100644 ---- a/arch/parisc/kernel/sys_parisc.c -+++ b/arch/parisc/kernel/sys_parisc.c -@@ -88,7 +88,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) - { - struct mm_struct *mm = current->mm; -- struct vm_area_struct *vma; -+ struct vm_area_struct *vma, *prev; - unsigned long task_size = TASK_SIZE; - int do_color_align, last_mmap; - struct vm_unmapped_area_info info; -@@ -115,9 +115,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - else - addr = PAGE_ALIGN(addr); - -- vma = find_vma(mm, addr); -+ vma = find_vma_prev(mm, addr, &prev); - if (task_size - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma)) && -+ (!prev || addr >= vm_end_gap(prev))) - goto found_addr; - } - -@@ -141,7 +142,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) - { -- struct vm_area_struct *vma; -+ struct vm_area_struct *vma, *prev; - struct mm_struct *mm = current->mm; - unsigned long addr = addr0; - int do_color_align, last_mmap; -@@ -175,9 +176,11 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - addr = COLOR_ALIGN(addr, last_mmap, pgoff); - else - addr = PAGE_ALIGN(addr); -- vma = find_vma(mm, addr); -+ -+ vma = find_vma_prev(mm, addr, &prev); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma)) && -+ (!prev || addr >= vm_end_gap(prev))) - goto found_addr; - } - -diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c -index 0f432a702870..6ad12b244770 100644 ---- a/arch/powerpc/mm/slice.c -+++ b/arch/powerpc/mm/slice.c -@@ -105,7 +105,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, - if ((mm->task_size - len) < addr) - return 0; - vma = find_vma(mm, addr); -- return (!vma || (addr + len) <= vma->vm_start); -+ return (!vma || (addr + len) <= vm_start_gap(vma)); - } - - static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) -diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c -index f2b6b1d9c804..126c4a9b9bf9 100644 ---- a/arch/s390/mm/mmap.c -+++ b/arch/s390/mm/mmap.c -@@ -97,7 +97,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -@@ -135,7 +135,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c -index 6777177807c2..7df7d5944188 100644 ---- a/arch/sh/mm/mmap.c -+++ b/arch/sh/mm/mmap.c -@@ -63,7 +63,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -@@ -113,7 +113,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c -index c690c8e16a96..7f0f7c01b297 100644 ---- a/arch/sparc/kernel/sys_sparc_64.c -+++ b/arch/sparc/kernel/sys_sparc_64.c -@@ -118,7 +118,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi - - vma = find_vma(mm, addr); - if (task_size - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -@@ -181,7 +181,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - - vma = find_vma(mm, addr); - if (task_size - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c -index da1142401bf4..ffa842b4d7d4 100644 ---- a/arch/sparc/mm/hugetlbpage.c -+++ b/arch/sparc/mm/hugetlbpage.c -@@ -115,7 +115,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - addr = ALIGN(addr, HPAGE_SIZE); - vma = find_vma(mm, addr); - if (task_size - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - if (mm->get_unmapped_area == arch_get_unmapped_area) -diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c -index c034dc3fe2d4..c97ee6c7f949 100644 ---- a/arch/tile/mm/hugetlbpage.c -+++ b/arch/tile/mm/hugetlbpage.c -@@ -232,7 +232,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - addr = ALIGN(addr, huge_page_size(h)); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - if (current->mm->get_unmapped_area == arch_get_unmapped_area) -diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c -index 10e0272d789a..136ad7c1ce7b 100644 ---- a/arch/x86/kernel/sys_x86_64.c -+++ b/arch/x86/kernel/sys_x86_64.c -@@ -143,7 +143,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (end - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -@@ -186,7 +186,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c -index 42982b26e32b..39bdaf3ac44a 100644 ---- a/arch/x86/mm/hugetlbpage.c -+++ b/arch/x86/mm/hugetlbpage.c -@@ -144,7 +144,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - addr = ALIGN(addr, huge_page_size(h)); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - if (mm->get_unmapped_area == arch_get_unmapped_area) -diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c -index 47b6436e41c2..3686a1db25b2 100644 ---- a/arch/x86/mm/numa_32.c -+++ b/arch/x86/mm/numa_32.c -@@ -100,5 +100,6 @@ void __init initmem_init(void) - printk(KERN_DEBUG "High memory starts at vaddr %08lx\n", - (ulong) pfn_to_kaddr(highstart_pfn)); - -+ __vmalloc_start_set = true; - setup_bootmem_allocator(); - } -diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c -index 83cf49685373..3aaaae18417c 100644 ---- a/arch/xtensa/kernel/syscall.c -+++ b/arch/xtensa/kernel/syscall.c -@@ -87,7 +87,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - /* At this point: (!vmm || addr < vmm->vm_end). */ - if (TASK_SIZE - len < addr) - return -ENOMEM; -- if (!vmm || addr + len <= vmm->vm_start) -+ if (!vmm || addr + len <= vm_start_gap(vmm)) - return addr; - addr = vmm->vm_end; - if (flags & MAP_SHARED) -diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c -index 1fa1deb6e91f..c395f9198fd2 100644 ---- a/drivers/cpufreq/cpufreq_conservative.c -+++ b/drivers/cpufreq/cpufreq_conservative.c -@@ -212,8 +212,8 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf, - int ret; - ret = sscanf(buf, "%u", &input); - -- /* cannot be lower than 11 otherwise freq will not fall */ -- if (ret != 1 || input < 11 || input > 100 || -+ /* cannot be lower than 1 otherwise freq will not fall */ -+ if (ret != 1 || input < 1 || input > 100 || - input >= cs_tuners->up_threshold) - return -EINVAL; - -diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c -index 9e6d1cdb7fcd..420478924a0c 100644 ---- a/drivers/iio/proximity/as3935.c -+++ b/drivers/iio/proximity/as3935.c -@@ -263,8 +263,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private) - - static void calibrate_as3935(struct as3935_state *st) - { -- mutex_lock(&st->lock); -- - /* mask disturber interrupt bit */ - as3935_write(st, AS3935_INT, BIT(5)); - -@@ -274,8 +272,6 @@ static void calibrate_as3935(struct as3935_state *st) - - mdelay(2); - as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); -- -- mutex_unlock(&st->lock); - } - - #ifdef CONFIG_PM_SLEEP -@@ -312,6 +308,8 @@ static int as3935_resume(struct device *dev) - val &= ~AS3935_AFE_PWR_BIT; - ret = as3935_write(st, AS3935_AFE_GAIN, val); - -+ calibrate_as3935(st); -+ - err_resume: - mutex_unlock(&st->lock); - -diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c -index e1907cd0c3b7..7613d1fee104 100644 ---- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c -+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c -@@ -123,15 +123,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) - memset(&tvdata,0,sizeof(tvdata)); - - eeprom = pvr2_eeprom_fetch(hdw); -- if (!eeprom) return -EINVAL; -- -- { -- struct i2c_client fake_client; -- /* Newer version expects a useless client interface */ -- fake_client.addr = hdw->eeprom_addr; -- fake_client.adapter = &hdw->i2c_adap; -- tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom); -- } -+ if (!eeprom) -+ return -EINVAL; -+ -+ tveeprom_hauppauge_analog(NULL, &tvdata, eeprom); - - trace_eeprom("eeprom assumed v4l tveeprom module"); - trace_eeprom("eeprom direct call results:"); -diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c -index 47f37683893a..3dc9ed2e0774 100644 ---- a/drivers/media/v4l2-core/videobuf2-core.c -+++ b/drivers/media/v4l2-core/videobuf2-core.c -@@ -793,7 +793,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs); - */ - void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) - { -- if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) -+ if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv) - return NULL; - - return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv); -diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c -index c30290f33430..fe51e9709210 100644 ---- a/drivers/mfd/omap-usb-tll.c -+++ b/drivers/mfd/omap-usb-tll.c -@@ -375,8 +375,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata) - * and use SDR Mode - */ - reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE -- | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF - | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); -+ reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; - } else if (pdata->port_mode[i] == - OMAP_EHCI_PORT_MODE_HSIC) { - /* -diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c -index 5484301d57d9..3dc61ea7dc64 100644 ---- a/drivers/misc/c2port/c2port-duramar2150.c -+++ b/drivers/misc/c2port/c2port-duramar2150.c -@@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void) - - duramar2150_c2port_dev = c2port_device_register("uc", - &duramar2150_c2port_ops, NULL); -- if (!duramar2150_c2port_dev) { -- ret = -ENODEV; -+ if (IS_ERR(duramar2150_c2port_dev)) { -+ ret = PTR_ERR(duramar2150_c2port_dev); - goto free_region; - } - -diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c -index cbc99d5649af..ae5709354546 100644 ---- a/drivers/net/can/usb/gs_usb.c -+++ b/drivers/net/can/usb/gs_usb.c -@@ -246,6 +246,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev) - sizeof(*dm), - 1000); - -+ kfree(dm); -+ - return rc; - } - -diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c -index 3cdb40fea5ee..f5cedbbc552a 100644 ---- a/drivers/staging/rtl8188eu/core/rtw_ap.c -+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c -@@ -894,7 +894,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) - return _FAIL; - - -- if (len > MAX_IE_SZ) -+ if (len < 0 || len > MAX_IE_SZ) - return _FAIL; - - pbss_network->IELength = len; -diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c -index 195acc868763..5d476916191b 100644 ---- a/drivers/tty/serial/efm32-uart.c -+++ b/drivers/tty/serial/efm32-uart.c -@@ -27,6 +27,7 @@ - #define UARTn_FRAME 0x04 - #define UARTn_FRAME_DATABITS__MASK 0x000f - #define UARTn_FRAME_DATABITS(n) ((n) - 3) -+#define UARTn_FRAME_PARITY__MASK 0x0300 - #define UARTn_FRAME_PARITY_NONE 0x0000 - #define UARTn_FRAME_PARITY_EVEN 0x0200 - #define UARTn_FRAME_PARITY_ODD 0x0300 -@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, - 16 * (4 + (clkdiv >> 6))); - - frame = efm32_uart_read32(efm_port, UARTn_FRAME); -- if (frame & UARTn_FRAME_PARITY_ODD) -+ switch (frame & UARTn_FRAME_PARITY__MASK) { -+ case UARTn_FRAME_PARITY_ODD: - *parity = 'o'; -- else if (frame & UARTn_FRAME_PARITY_EVEN) -+ break; -+ case UARTn_FRAME_PARITY_EVEN: - *parity = 'e'; -- else -+ break; -+ default: - *parity = 'n'; -+ } - - *bits = (frame & UARTn_FRAME_DATABITS__MASK) - - UARTn_FRAME_DATABITS(4) + 4; -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index c3f4f2ab7b33..b403596818db 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -2511,6 +2511,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, - hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex), - GFP_KERNEL); - if (!hcd->bandwidth_mutex) { -+ kfree(hcd->address0_mutex); - kfree(hcd); - dev_dbg(dev, "hcd bandwidth mutex alloc failed\n"); - return NULL; -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index b627392ad52a..1d59d489a1ad 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -1318,7 +1318,13 @@ static int hub_configure(struct usb_hub *hub, - if (ret < 0) { - message = "can't read hub descriptor"; - goto fail; -- } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { -+ } -+ -+ maxchild = USB_MAXCHILDREN; -+ if (hub_is_superspeed(hdev)) -+ maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS); -+ -+ if (hub->descriptor->bNbrPorts > maxchild) { - message = "hub has too many ports!"; - ret = -ENODEV; - goto fail; -diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c -index 2f1fb7e7aa54..9eba51b92f72 100644 ---- a/drivers/usb/dwc3/dwc3-exynos.c -+++ b/drivers/usb/dwc3/dwc3-exynos.c -@@ -148,7 +148,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev) - exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk"); - if (IS_ERR(exynos->axius_clk)) { - dev_err(dev, "no AXI UpScaler clk specified\n"); -- return -ENODEV; -+ ret = -ENODEV; -+ goto axius_clk_err; - } - clk_prepare_enable(exynos->axius_clk); - } else { -@@ -206,6 +207,7 @@ err3: - regulator_disable(exynos->vdd33); - err2: - clk_disable_unprepare(exynos->axius_clk); -+axius_clk_err: - clk_disable_unprepare(exynos->susp_clk); - clk_disable_unprepare(exynos->clk); - return ret; -diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c -index de014436fb22..43ce2cfcdb4d 100644 ---- a/drivers/usb/gadget/legacy/inode.c -+++ b/drivers/usb/gadget/legacy/inode.c -@@ -1676,9 +1676,10 @@ static void - gadgetfs_suspend (struct usb_gadget *gadget) - { - struct dev_data *dev = get_gadget_data (gadget); -+ unsigned long flags; - - INFO (dev, "suspended from state %d\n", dev->state); -- spin_lock (&dev->lock); -+ spin_lock_irqsave(&dev->lock, flags); - switch (dev->state) { - case STATE_DEV_SETUP: // VERY odd... host died?? - case STATE_DEV_CONNECTED: -@@ -1689,7 +1690,7 @@ gadgetfs_suspend (struct usb_gadget *gadget) - default: - break; - } -- spin_unlock (&dev->lock); -+ spin_unlock_irqrestore(&dev->lock, flags); - } - - static struct usb_gadget_driver gadgetfs_driver = { -diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c -index 6610f7a023d3..64f404a1a072 100644 ---- a/drivers/usb/gadget/udc/dummy_hcd.c -+++ b/drivers/usb/gadget/udc/dummy_hcd.c -@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd) - /* Report reset and disconnect events to the driver */ - if (dum->driver && (disconnect || reset)) { - stop_activity(dum); -- spin_unlock(&dum->lock); - if (reset) - usb_gadget_udc_reset(&dum->gadget, dum->driver); - else - dum->driver->disconnect(&dum->gadget); -- spin_lock(&dum->lock); - } - } else if (dum_hcd->active != dum_hcd->old_active) { -- if (dum_hcd->old_active && dum->driver->suspend) { -- spin_unlock(&dum->lock); -+ if (dum_hcd->old_active && dum->driver->suspend) - dum->driver->suspend(&dum->gadget); -- spin_lock(&dum->lock); -- } else if (!dum_hcd->old_active && dum->driver->resume) { -- spin_unlock(&dum->lock); -+ else if (!dum_hcd->old_active && dum->driver->resume) - dum->driver->resume(&dum->gadget); -- spin_lock(&dum->lock); -- } - } - - dum_hcd->old_status = dum_hcd->port_status; -@@ -985,7 +978,9 @@ static int dummy_udc_stop(struct usb_gadget *g) - struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); - struct dummy *dum = dum_hcd->dum; - -+ spin_lock_irq(&dum->lock); - dum->driver = NULL; -+ spin_unlock_irq(&dum->lock); - - return 0; - } -@@ -2011,7 +2006,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) - HUB_CHAR_COMMON_OCPM); - desc->bNbrPorts = 1; - desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/ -- desc->u.ss.DeviceRemovable = 0xffff; -+ desc->u.ss.DeviceRemovable = 0; - } - - static inline void hub_descriptor(struct usb_hub_descriptor *desc) -@@ -2023,8 +2018,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc) - HUB_CHAR_INDV_PORT_LPSM | - HUB_CHAR_COMMON_OCPM); - desc->bNbrPorts = 1; -- desc->u.hs.DeviceRemovable[0] = 0xff; -- desc->u.hs.DeviceRemovable[1] = 0xff; -+ desc->u.hs.DeviceRemovable[0] = 0; -+ desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */ - } - - static int dummy_hub_control( -diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c -index 6706aef907f4..a47de8c31ce9 100644 ---- a/drivers/usb/gadget/udc/net2280.c -+++ b/drivers/usb/gadget/udc/net2280.c -@@ -2425,11 +2425,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver) - nuke(&dev->ep[i]); - - /* report disconnect; the driver is already quiesced */ -- if (driver) { -- spin_unlock(&dev->lock); -+ if (driver) - driver->disconnect(&dev->gadget); -- spin_lock(&dev->lock); -- } - - usb_reinit(dev); - } -@@ -3275,8 +3272,6 @@ next_endpoints: - BIT(PCI_RETRY_ABORT_INTERRUPT)) - - static void handle_stat1_irqs(struct net2280 *dev, u32 stat) --__releases(dev->lock) --__acquires(dev->lock) - { - struct net2280_ep *ep; - u32 tmp, num, mask, scratch; -@@ -3317,14 +3312,12 @@ __acquires(dev->lock) - if (disconnect || reset) { - stop_activity(dev, dev->driver); - ep0_start(dev); -- spin_unlock(&dev->lock); - if (reset) - usb_gadget_udc_reset - (&dev->gadget, dev->driver); - else - (dev->driver->disconnect) - (&dev->gadget); -- spin_lock(&dev->lock); - return; - } - } -diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c -index 4cbd0633c5c2..a11c2c8bda53 100644 ---- a/drivers/usb/host/r8a66597-hcd.c -+++ b/drivers/usb/host/r8a66597-hcd.c -@@ -1269,7 +1269,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) - time = 30; - break; - default: -- time = 300; -+ time = 50; - break; - } - -@@ -1785,6 +1785,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597) - pipe = td->pipe; - pipe_stop(r8a66597, pipe); - -+ /* Select a different address or endpoint */ - new_td = td; - do { - list_move_tail(&new_td->queue, -@@ -1794,7 +1795,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597) - new_td = td; - break; - } -- } while (td != new_td && td->address == new_td->address); -+ } while (td != new_td && td->address == new_td->address && -+ td->pipe->info.epnum == new_td->pipe->info.epnum); - - start_transfer(r8a66597, new_td); - -diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c -index 30c4ae80c8f9..e8f990642281 100644 ---- a/drivers/usb/host/xhci-pci.c -+++ b/drivers/usb/host/xhci-pci.c -@@ -198,6 +198,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) - if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == 0x1042) - xhci->quirks |= XHCI_BROKEN_STREAMS; -+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && -+ pdev->device == 0x1142) -+ xhci->quirks |= XHCI_TRUST_TX_LENGTH; - - if (xhci->quirks & XHCI_RESET_ON_RESUME) - xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, -diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c -index ec5c8325b503..0525ebc3aea2 100644 ---- a/fs/configfs/symlink.c -+++ b/fs/configfs/symlink.c -@@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item, - ret = -ENOMEM; - sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); - if (sl) { -- sl->sl_target = config_item_get(item); - spin_lock(&configfs_dirent_lock); - if (target_sd->s_type & CONFIGFS_USET_DROPPING) { - spin_unlock(&configfs_dirent_lock); -- config_item_put(item); - kfree(sl); - return -ENOENT; - } -+ sl->sl_target = config_item_get(item); - list_add(&sl->sl_list, &target_sd->s_links); - spin_unlock(&configfs_dirent_lock); - ret = configfs_create_link(sl, parent_item->ci_dentry, -diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c -index 595ebdb41846..a17da8b57fc6 100644 ---- a/fs/hugetlbfs/inode.c -+++ b/fs/hugetlbfs/inode.c -@@ -191,7 +191,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - addr = ALIGN(addr, huge_page_size(h)); - vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index db1a1427c27a..07ef85e19fbc 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -295,11 +295,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) - - /* We don't show the stack guard page in /proc/maps */ - start = vma->vm_start; -- if (stack_guard_page_start(vma, start)) -- start += PAGE_SIZE; - end = vma->vm_end; -- if (stack_guard_page_end(vma, end)) -- end -= PAGE_SIZE; - - seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); - seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", -diff --git a/include/linux/mm.h b/include/linux/mm.h -index f0ffa01c90d9..55f950afb60d 100644 ---- a/include/linux/mm.h -+++ b/include/linux/mm.h -@@ -1278,39 +1278,11 @@ int clear_page_dirty_for_io(struct page *page); - - int get_cmdline(struct task_struct *task, char *buffer, int buflen); - --/* Is the vma a continuation of the stack vma above it? */ --static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) --{ -- return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); --} -- - static inline bool vma_is_anonymous(struct vm_area_struct *vma) - { - return !vma->vm_ops; - } - --static inline int stack_guard_page_start(struct vm_area_struct *vma, -- unsigned long addr) --{ -- return (vma->vm_flags & VM_GROWSDOWN) && -- (vma->vm_start == addr) && -- !vma_growsdown(vma->vm_prev, addr); --} -- --/* Is the vma a continuation of the stack vma below it? */ --static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr) --{ -- return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP); --} -- --static inline int stack_guard_page_end(struct vm_area_struct *vma, -- unsigned long addr) --{ -- return (vma->vm_flags & VM_GROWSUP) && -- (vma->vm_end == addr) && -- !vma_growsup(vma->vm_next, addr); --} -- - int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t); - - extern unsigned long move_page_tables(struct vm_area_struct *vma, -@@ -2012,6 +1984,7 @@ void page_cache_async_readahead(struct address_space *mapping, - pgoff_t offset, - unsigned long size); - -+extern unsigned long stack_guard_gap; - /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ - extern int expand_stack(struct vm_area_struct *vma, unsigned long address); - -@@ -2040,6 +2013,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m - return vma; - } - -+static inline unsigned long vm_start_gap(struct vm_area_struct *vma) -+{ -+ unsigned long vm_start = vma->vm_start; -+ -+ if (vma->vm_flags & VM_GROWSDOWN) { -+ vm_start -= stack_guard_gap; -+ if (vm_start > vma->vm_start) -+ vm_start = 0; -+ } -+ return vm_start; -+} -+ -+static inline unsigned long vm_end_gap(struct vm_area_struct *vma) -+{ -+ unsigned long vm_end = vma->vm_end; -+ -+ if (vma->vm_flags & VM_GROWSUP) { -+ vm_end += stack_guard_gap; -+ if (vm_end < vma->vm_end) -+ vm_end = -PAGE_SIZE; -+ } -+ return vm_end; -+} -+ - static inline unsigned long vma_pages(struct vm_area_struct *vma) - { - return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; -diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h -index 331499d597fa..9ce10d4a0245 100644 ---- a/include/uapi/linux/usb/ch11.h -+++ b/include/uapi/linux/usb/ch11.h -@@ -22,6 +22,9 @@ - */ - #define USB_MAXCHILDREN 31 - -+/* See USB 3.1 spec Table 10-5 */ -+#define USB_SS_MAXPORTS 15 -+ - /* - * Hub request types - */ -diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c -index 6ead200370da..a079ed14f230 100644 ---- a/kernel/irq/manage.c -+++ b/kernel/irq/manage.c -@@ -1287,8 +1287,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) - ret = __irq_set_trigger(desc, - new->flags & IRQF_TRIGGER_MASK); - -- if (ret) -+ if (ret) { -+ irq_release_resources(desc); - goto out_mask; -+ } - } - - desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ -diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c -index 7fbba635a549..2c3a23d77704 100644 ---- a/kernel/time/alarmtimer.c -+++ b/kernel/time/alarmtimer.c -@@ -339,7 +339,7 @@ void alarm_start_relative(struct alarm *alarm, ktime_t start) - { - struct alarm_base *base = &alarm_bases[alarm->type]; - -- start = ktime_add(start, base->gettime()); -+ start = ktime_add_safe(start, base->gettime()); - alarm_start(alarm, start); - } - EXPORT_SYMBOL_GPL(alarm_start_relative); -@@ -425,7 +425,7 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) - overrun++; - } - -- alarm->node.expires = ktime_add(alarm->node.expires, interval); -+ alarm->node.expires = ktime_add_safe(alarm->node.expires, interval); - return overrun; - } - EXPORT_SYMBOL_GPL(alarm_forward); -@@ -611,13 +611,21 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, - - /* start the timer */ - timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); -+ -+ /* -+ * Rate limit to the tick as a hot fix to prevent DOS. Will be -+ * mopped up later. -+ */ -+ if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) -+ timr->it.alarm.interval = ktime_set(0, TICK_NSEC); -+ - exp = timespec_to_ktime(new_setting->it_value); - /* Convert (if necessary) to absolute time */ - if (flags != TIMER_ABSTIME) { - ktime_t now; - - now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime(); -- exp = ktime_add(now, exp); -+ exp = ktime_add_safe(now, exp); - } - - alarm_start(&timr->it.alarm.alarmtimer, exp); -diff --git a/mm/gup.c b/mm/gup.c -index 4b0b7e7d1136..b599526db9f7 100644 ---- a/mm/gup.c -+++ b/mm/gup.c -@@ -312,11 +312,6 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, - /* mlock all present pages, but do not fault in new pages */ - if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK) - return -ENOENT; -- /* For mm_populate(), just skip the stack guard page. */ -- if ((*flags & FOLL_POPULATE) && -- (stack_guard_page_start(vma, address) || -- stack_guard_page_end(vma, address + PAGE_SIZE))) -- return -ENOENT; - if (*flags & FOLL_WRITE) - fault_flags |= FAULT_FLAG_WRITE; - if (nonblocking) -diff --git a/mm/memory-failure.c b/mm/memory-failure.c -index 43aee7ab143e..091fe9b06663 100644 ---- a/mm/memory-failure.c -+++ b/mm/memory-failure.c -@@ -1208,7 +1208,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) - * page_remove_rmap() in try_to_unmap_one(). So to determine page status - * correctly, we save a copy of the page flags at this time. - */ -- page_flags = p->flags; -+ if (PageHuge(p)) -+ page_flags = hpage->flags; -+ else -+ page_flags = p->flags; - - /* - * unpoison always clear PG_hwpoison inside page lock -diff --git a/mm/memory.c b/mm/memory.c -index 76dcee317714..e6fa13484447 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -2662,40 +2662,6 @@ out_release: - } - - /* -- * This is like a special single-page "expand_{down|up}wards()", -- * except we must first make sure that 'address{-|+}PAGE_SIZE' -- * doesn't hit another vma. -- */ --static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) --{ -- address &= PAGE_MASK; -- if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { -- struct vm_area_struct *prev = vma->vm_prev; -- -- /* -- * Is there a mapping abutting this one below? -- * -- * That's only ok if it's the same stack mapping -- * that has gotten split.. -- */ -- if (prev && prev->vm_end == address) -- return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; -- -- return expand_downwards(vma, address - PAGE_SIZE); -- } -- if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { -- struct vm_area_struct *next = vma->vm_next; -- -- /* As VM_GROWSDOWN but s/below/above/ */ -- if (next && next->vm_start == address + PAGE_SIZE) -- return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; -- -- return expand_upwards(vma, address + PAGE_SIZE); -- } -- return 0; --} -- --/* - * We enter with non-exclusive mmap_sem (to exclude vma changes, - * but allow concurrent faults), and pte mapped but not yet locked. - * We return with mmap_sem still held, but pte unmapped and unlocked. -@@ -2715,10 +2681,6 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, - if (vma->vm_flags & VM_SHARED) - return VM_FAULT_SIGBUS; - -- /* Check if we need to add a guard page to the stack */ -- if (check_stack_guard_page(vma, address) < 0) -- return VM_FAULT_SIGSEGV; -- - /* Use the zero-page for reads */ - if (!(flags & FAULT_FLAG_WRITE) && !mm_forbids_zeropage(mm)) { - entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), -diff --git a/mm/mmap.c b/mm/mmap.c -index 455772a05e54..0990f8bc0fbe 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -288,6 +288,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) - unsigned long retval; - unsigned long newbrk, oldbrk; - struct mm_struct *mm = current->mm; -+ struct vm_area_struct *next; - unsigned long min_brk; - bool populate; - -@@ -332,7 +333,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) - } - - /* Check against existing mmap mappings. */ -- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) -+ next = find_vma(mm, oldbrk); -+ if (next && newbrk + PAGE_SIZE > vm_start_gap(next)) - goto out; - - /* Ok, looks good - let it rip. */ -@@ -355,10 +357,22 @@ out: - - static long vma_compute_subtree_gap(struct vm_area_struct *vma) - { -- unsigned long max, subtree_gap; -- max = vma->vm_start; -- if (vma->vm_prev) -- max -= vma->vm_prev->vm_end; -+ unsigned long max, prev_end, subtree_gap; -+ -+ /* -+ * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we -+ * allow two stack_guard_gaps between them here, and when choosing -+ * an unmapped area; whereas when expanding we only require one. -+ * That's a little inconsistent, but keeps the code here simpler. -+ */ -+ max = vm_start_gap(vma); -+ if (vma->vm_prev) { -+ prev_end = vm_end_gap(vma->vm_prev); -+ if (max > prev_end) -+ max -= prev_end; -+ else -+ max = 0; -+ } - if (vma->vm_rb.rb_left) { - subtree_gap = rb_entry(vma->vm_rb.rb_left, - struct vm_area_struct, vm_rb)->rb_subtree_gap; -@@ -451,7 +465,7 @@ static void validate_mm(struct mm_struct *mm) - anon_vma_unlock_read(anon_vma); - } - -- highest_address = vma->vm_end; -+ highest_address = vm_end_gap(vma); - vma = vma->vm_next; - i++; - } -@@ -620,7 +634,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, - if (vma->vm_next) - vma_gap_update(vma->vm_next); - else -- mm->highest_vm_end = vma->vm_end; -+ mm->highest_vm_end = vm_end_gap(vma); - - /* - * vma->vm_prev wasn't known when we followed the rbtree to find the -@@ -866,7 +880,7 @@ again: remove_next = 1 + (end > next->vm_end); - vma_gap_update(vma); - if (end_changed) { - if (!next) -- mm->highest_vm_end = end; -+ mm->highest_vm_end = vm_end_gap(vma); - else if (!adjust_next) - vma_gap_update(next); - } -@@ -909,7 +923,7 @@ again: remove_next = 1 + (end > next->vm_end); - else if (next) - vma_gap_update(next); - else -- mm->highest_vm_end = end; -+ VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma)); - } - if (insert && file) - uprobe_mmap(insert); -@@ -1741,7 +1755,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) - - while (true) { - /* Visit left subtree if it looks promising */ -- gap_end = vma->vm_start; -+ gap_end = vm_start_gap(vma); - if (gap_end >= low_limit && vma->vm_rb.rb_left) { - struct vm_area_struct *left = - rb_entry(vma->vm_rb.rb_left, -@@ -1752,12 +1766,13 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) - } - } - -- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; -+ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; - check_current: - /* Check if current node has a suitable gap */ - if (gap_start > high_limit) - return -ENOMEM; -- if (gap_end >= low_limit && gap_end - gap_start >= length) -+ if (gap_end >= low_limit && -+ gap_end > gap_start && gap_end - gap_start >= length) - goto found; - - /* Visit right subtree if it looks promising */ -@@ -1779,8 +1794,8 @@ check_current: - vma = rb_entry(rb_parent(prev), - struct vm_area_struct, vm_rb); - if (prev == vma->vm_rb.rb_left) { -- gap_start = vma->vm_prev->vm_end; -- gap_end = vma->vm_start; -+ gap_start = vm_end_gap(vma->vm_prev); -+ gap_end = vm_start_gap(vma); - goto check_current; - } - } -@@ -1844,7 +1859,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) - - while (true) { - /* Visit right subtree if it looks promising */ -- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; -+ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; - if (gap_start <= high_limit && vma->vm_rb.rb_right) { - struct vm_area_struct *right = - rb_entry(vma->vm_rb.rb_right, -@@ -1857,10 +1872,11 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) - - check_current: - /* Check if current node has a suitable gap */ -- gap_end = vma->vm_start; -+ gap_end = vm_start_gap(vma); - if (gap_end < low_limit) - return -ENOMEM; -- if (gap_start <= high_limit && gap_end - gap_start >= length) -+ if (gap_start <= high_limit && -+ gap_end > gap_start && gap_end - gap_start >= length) - goto found; - - /* Visit left subtree if it looks promising */ -@@ -1883,7 +1899,7 @@ check_current: - struct vm_area_struct, vm_rb); - if (prev == vma->vm_rb.rb_right) { - gap_start = vma->vm_prev ? -- vma->vm_prev->vm_end : 0; -+ vm_end_gap(vma->vm_prev) : 0; - goto check_current; - } - } -@@ -1921,7 +1937,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) - { - struct mm_struct *mm = current->mm; -- struct vm_area_struct *vma; -+ struct vm_area_struct *vma, *prev; - struct vm_unmapped_area_info info; - - if (len > TASK_SIZE - mmap_min_addr) -@@ -1932,9 +1948,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, - - if (addr) { - addr = PAGE_ALIGN(addr); -- vma = find_vma(mm, addr); -+ vma = find_vma_prev(mm, addr, &prev); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma)) && -+ (!prev || addr >= vm_end_gap(prev))) - return addr; - } - -@@ -1957,7 +1974,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - const unsigned long len, const unsigned long pgoff, - const unsigned long flags) - { -- struct vm_area_struct *vma; -+ struct vm_area_struct *vma, *prev; - struct mm_struct *mm = current->mm; - unsigned long addr = addr0; - struct vm_unmapped_area_info info; -@@ -1972,9 +1989,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, - /* requesting a specific address */ - if (addr) { - addr = PAGE_ALIGN(addr); -- vma = find_vma(mm, addr); -+ vma = find_vma_prev(mm, addr, &prev); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && -- (!vma || addr + len <= vma->vm_start)) -+ (!vma || addr + len <= vm_start_gap(vma)) && -+ (!prev || addr >= vm_end_gap(prev))) - return addr; - } - -@@ -2099,21 +2117,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr, - * update accounting. This is shared with both the - * grow-up and grow-down cases. - */ --static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow) -+static int acct_stack_growth(struct vm_area_struct *vma, -+ unsigned long size, unsigned long grow) - { - struct mm_struct *mm = vma->vm_mm; - struct rlimit *rlim = current->signal->rlim; -- unsigned long new_start, actual_size; -+ unsigned long new_start; - - /* address space limit tests */ - if (!may_expand_vm(mm, grow)) - return -ENOMEM; - - /* Stack limit test */ -- actual_size = size; -- if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) -- actual_size -= PAGE_SIZE; -- if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur)) -+ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur)) - return -ENOMEM; - - /* mlock limit tests */ -@@ -2151,16 +2167,32 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns - int expand_upwards(struct vm_area_struct *vma, unsigned long address) - { - struct mm_struct *mm = vma->vm_mm; -+ struct vm_area_struct *next; -+ unsigned long gap_addr; - int error = 0; - - if (!(vma->vm_flags & VM_GROWSUP)) - return -EFAULT; - -- /* Guard against wrapping around to address 0. */ -- if (address < PAGE_ALIGN(address+4)) -- address = PAGE_ALIGN(address+4); -- else -+ /* Guard against exceeding limits of the address space. */ -+ address &= PAGE_MASK; -+ if (address >= TASK_SIZE) - return -ENOMEM; -+ address += PAGE_SIZE; -+ -+ /* Enforce stack_guard_gap */ -+ gap_addr = address + stack_guard_gap; -+ -+ /* Guard against overflow */ -+ if (gap_addr < address || gap_addr > TASK_SIZE) -+ gap_addr = TASK_SIZE; -+ -+ next = vma->vm_next; -+ if (next && next->vm_start < gap_addr) { -+ if (!(next->vm_flags & VM_GROWSUP)) -+ return -ENOMEM; -+ /* Check that both stack segments have the same anon_vma? */ -+ } - - /* We must make sure the anon_vma is allocated. */ - if (unlikely(anon_vma_prepare(vma))) -@@ -2206,7 +2238,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) - if (vma->vm_next) - vma_gap_update(vma->vm_next); - else -- mm->highest_vm_end = address; -+ mm->highest_vm_end = vm_end_gap(vma); - spin_unlock(&mm->page_table_lock); - - perf_event_mmap(vma); -@@ -2227,6 +2259,8 @@ int expand_downwards(struct vm_area_struct *vma, - unsigned long address) - { - struct mm_struct *mm = vma->vm_mm; -+ struct vm_area_struct *prev; -+ unsigned long gap_addr; - int error; - - address &= PAGE_MASK; -@@ -2234,6 +2268,17 @@ int expand_downwards(struct vm_area_struct *vma, - if (error) - return error; - -+ /* Enforce stack_guard_gap */ -+ gap_addr = address - stack_guard_gap; -+ if (gap_addr > address) -+ return -ENOMEM; -+ prev = vma->vm_prev; -+ if (prev && prev->vm_end > gap_addr) { -+ if (!(prev->vm_flags & VM_GROWSDOWN)) -+ return -ENOMEM; -+ /* Check that both stack segments have the same anon_vma? */ -+ } -+ - /* We must make sure the anon_vma is allocated. */ - if (unlikely(anon_vma_prepare(vma))) - return -ENOMEM; -@@ -2289,28 +2334,25 @@ int expand_downwards(struct vm_area_struct *vma, - return error; - } - --/* -- * Note how expand_stack() refuses to expand the stack all the way to -- * abut the next virtual mapping, *unless* that mapping itself is also -- * a stack mapping. We want to leave room for a guard page, after all -- * (the guard page itself is not added here, that is done by the -- * actual page faulting logic) -- * -- * This matches the behavior of the guard page logic (see mm/memory.c: -- * check_stack_guard_page()), which only allows the guard page to be -- * removed under these circumstances. -- */ -+/* enforced gap between the expanding stack and other mappings. */ -+unsigned long stack_guard_gap = 256UL<len - hdrlen - MICHAEL_MIC_LEN; - key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; - michael_mic(key, hdr, data, data_len, mic); -- if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) -+ if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN)) - goto mic_fail; - - /* remove Michael MIC from payload */ -@@ -1044,7 +1045,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) - bip_aad(skb, aad); - ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad, - skb->data + 24, skb->len - 24, mic); -- if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { -+ if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { - key->u.aes_cmac.icverrors++; - return RX_DROP_UNUSABLE; - } -@@ -1094,7 +1095,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) - bip_aad(skb, aad); - ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, - skb->data + 24, skb->len - 24, mic); -- if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { -+ if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { - key->u.aes_cmac.icverrors++; - return RX_DROP_UNUSABLE; - } -@@ -1198,7 +1199,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) - if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, - skb->data + 24, skb->len - 24, - mic) < 0 || -- memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { -+ crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { - key->u.aes_gmac.icverrors++; - return RX_DROP_UNUSABLE; - } diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.74-75.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.74-75.patch deleted file mode 100644 index 79dc86567..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.74-75.patch +++ /dev/null @@ -1,1018 +0,0 @@ -diff --git a/Makefile b/Makefile -index 1f75507acbf4..696d15d8ad5d 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 74 -+SUBLEVEL = 75 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c -index 7c053f281406..1138fec3dd65 100644 ---- a/arch/powerpc/kernel/kprobes.c -+++ b/arch/powerpc/kernel/kprobes.c -@@ -514,6 +514,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) - #endif - #endif - -+ /* -+ * jprobes use jprobe_return() which skips the normal return -+ * path of the function, and this messes up the accounting of the -+ * function graph tracer. -+ * -+ * Pause function graph tracing while performing the jprobe function. -+ */ -+ pause_graph_tracing(); -+ - return 1; - } - -@@ -536,6 +545,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) - * saved regs... - */ - memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); -+ /* It's OK to start function graph tracing again */ -+ unpause_graph_tracing(); - preempt_enable_no_resched(); - return 1; - } -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 3c3a367b6e59..396dc44e783b 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -2693,6 +2693,27 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) - return -EINVAL; - } - -+ /* -+ * Don't allow entry with a suspended transaction, because -+ * the guest entry/exit code will lose it. -+ * If the guest has TM enabled, save away their TM-related SPRs -+ * (they will get restored by the TM unavailable interrupt). -+ */ -+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -+ if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs && -+ (current->thread.regs->msr & MSR_TM)) { -+ if (MSR_TM_ACTIVE(current->thread.regs->msr)) { -+ run->exit_reason = KVM_EXIT_FAIL_ENTRY; -+ run->fail_entry.hardware_entry_failure_reason = 0; -+ return -EINVAL; -+ } -+ current->thread.tm_tfhar = mfspr(SPRN_TFHAR); -+ current->thread.tm_tfiar = mfspr(SPRN_TFIAR); -+ current->thread.tm_texasr = mfspr(SPRN_TEXASR); -+ current->thread.regs->msr &= ~MSR_TM; -+ } -+#endif -+ - kvmppc_core_prepare_to_enter(vcpu); - - /* No need to go into the guest when all we'll do is come back out */ -diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S -index 4c48b487698c..0b48ce40d351 100644 ---- a/arch/powerpc/mm/slb_low.S -+++ b/arch/powerpc/mm/slb_low.S -@@ -179,6 +179,16 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) - b slb_finish_load - - 8: /* invalid EA */ -+ /* -+ * It's possible the bad EA is too large to fit in the SLB cache, which -+ * would mean we'd fail to invalidate it on context switch. So mark the -+ * SLB cache as full so we force a full flush. We also set cr7+eq to -+ * mark the address as a kernel address, so slb_finish_load() skips -+ * trying to insert it into the SLB cache. -+ */ -+ li r9,SLB_CACHE_ENTRIES + 1 -+ sth r9,PACASLBCACHEPTR(r13) -+ crset 4*cr7+eq - li r10,0 /* BAD_VSID */ - li r9,0 /* BAD_VSID */ - li r11,SLB_VSID_USER /* flags don't much matter */ -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c -index 51a9942cdb40..f4cae5357e40 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c -@@ -681,6 +681,10 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev) - DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n", - adev->clock.default_dispclk / 100); - adev->clock.default_dispclk = 60000; -+ } else if (adev->clock.default_dispclk <= 60000) { -+ DRM_INFO("Changing default dispclk from %dMhz to 625Mhz\n", -+ adev->clock.default_dispclk / 100); -+ adev->clock.default_dispclk = 62500; - } - adev->clock.dp_extclk = - le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); -diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c -index 49aa35016653..247b088990dc 100644 ---- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c -+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c -@@ -164,7 +164,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state) - struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; - int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); -- ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; -+ ENABLE_DISP_POWER_GATING_PS_ALLOCATION args; - - memset(&args, 0, sizeof(args)); - -@@ -177,7 +177,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state) - void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev) - { - int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); -- ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; -+ ENABLE_DISP_POWER_GATING_PS_ALLOCATION args; - - memset(&args, 0, sizeof(args)); - -diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c -index a9b01bcf7d0a..fcecaf5b5526 100644 ---- a/drivers/gpu/drm/radeon/radeon_combios.c -+++ b/drivers/gpu/drm/radeon/radeon_combios.c -@@ -3394,6 +3394,13 @@ void radeon_combios_asic_init(struct drm_device *dev) - rdev->pdev->subsystem_vendor == 0x103c && - rdev->pdev->subsystem_device == 0x280a) - return; -+ /* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume -+ * - it hangs on resume inside the dynclk 1 table. -+ */ -+ if (rdev->family == CHIP_RS400 && -+ rdev->pdev->subsystem_vendor == 0x1179 && -+ rdev->pdev->subsystem_device == 0xff31) -+ return; - - /* DYN CLK 1 */ - table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index 4aa2cbe4c85f..a77521695c9a 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -127,6 +127,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = { - * https://bugzilla.kernel.org/show_bug.cgi?id=51381 - */ - { PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, -+ /* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU -+ * https://bugs.freedesktop.org/show_bug.cgi?id=101491 -+ */ -+ { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, - /* macbook pro 8.2 */ - { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP }, - { 0, 0, 0, 0, 0 }, -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index e37030624165..c7f8b70d15ee 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -285,6 +285,9 @@ - #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 - #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a - -+#define USB_VENDOR_ID_DELL 0x413c -+#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE 0x301a -+ - #define USB_VENDOR_ID_DELORME 0x1163 - #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 - #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 -diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c -index 6ca6ab00fa93..ce1543d69acb 100644 ---- a/drivers/hid/usbhid/hid-quirks.c -+++ b/drivers/hid/usbhid/hid-quirks.c -@@ -72,6 +72,7 @@ static const struct hid_blacklist { - { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, -+ { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, -diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h -index e7b96f1ac2c5..5be14ad29d46 100644 ---- a/drivers/input/serio/i8042-x86ia64io.h -+++ b/drivers/input/serio/i8042-x86ia64io.h -@@ -788,6 +788,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), - }, - }, -+ { -+ /* Fujitsu UH554 laptop */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"), -+ }, -+ }, - { } - }; - -diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c -index 37e4135ab213..64d6f053c2a5 100644 ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1057,6 +1057,13 @@ static int spansion_quad_enable(struct spi_nor *nor) - return -EINVAL; - } - -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) { -+ dev_err(nor->dev, -+ "timeout while writing configuration register\n"); -+ return ret; -+ } -+ - /* read back and check it */ - ret = read_cr(nor); - if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { -diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c -index d2701c53ed68..ebec2dceff45 100644 ---- a/drivers/net/phy/marvell.c -+++ b/drivers/net/phy/marvell.c -@@ -822,8 +822,6 @@ static int marvell_read_status(struct phy_device *phydev) - phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) | - mii_lpa_to_ethtool_lpa_t(lpa); - -- lpa &= adv; -- - if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) - phydev->duplex = DUPLEX_FULL; - else -diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c -index c0b4e65267af..46fe1ae919a3 100644 ---- a/drivers/net/phy/mdio-bcm-iproc.c -+++ b/drivers/net/phy/mdio-bcm-iproc.c -@@ -81,8 +81,6 @@ static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg) - if (rc) - return rc; - -- iproc_mdio_config_clk(priv->base); -- - /* Prepare the read operation */ - cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | - (reg << MII_DATA_RA_SHIFT) | -@@ -112,8 +110,6 @@ static int iproc_mdio_write(struct mii_bus *bus, int phy_id, - if (rc) - return rc; - -- iproc_mdio_config_clk(priv->base); -- - /* Prepare the write operation */ - cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | - (reg << MII_DATA_RA_SHIFT) | -@@ -163,6 +159,8 @@ static int iproc_mdio_probe(struct platform_device *pdev) - bus->read = iproc_mdio_read; - bus->write = iproc_mdio_write; - -+ iproc_mdio_config_clk(priv->base); -+ - rc = of_mdiobus_register(bus, pdev->dev.of_node); - if (rc) { - dev_err(&pdev->dev, "MDIO bus registration failed\n"); -diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h -index 044253dca30a..b8a5a8e8f57d 100644 ---- a/drivers/nvme/host/nvme.h -+++ b/drivers/nvme/host/nvme.h -@@ -27,6 +27,13 @@ enum { - NVME_NS_LIGHTNVM = 1, - }; - -+/* The below value is the specific amount of delay needed before checking -+ * readiness in case of the PCI_DEVICE(0x1c58, 0x0003), which needs the -+ * NVME_QUIRK_DELAY_BEFORE_CHK_RDY quirk enabled. The value (in ms) was -+ * found empirically. -+ */ -+#define NVME_QUIRK_DELAY_AMOUNT 2000 -+ - /* - * Represents an NVM Express device. Each nvme_dev is a PCI function. - */ -diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c -index c851bc53831c..4c673d45f1bd 100644 ---- a/drivers/nvme/host/pci.c -+++ b/drivers/nvme/host/pci.c -@@ -1633,10 +1633,15 @@ static int nvme_wait_ready(struct nvme_dev *dev, u64 cap, bool enabled) - */ - static int nvme_disable_ctrl(struct nvme_dev *dev, u64 cap) - { -+ struct pci_dev *pdev = to_pci_dev(dev->dev); -+ - dev->ctrl_config &= ~NVME_CC_SHN_MASK; - dev->ctrl_config &= ~NVME_CC_ENABLE; - writel(dev->ctrl_config, &dev->bar->cc); - -+ if (pdev->vendor == 0x1c58 && pdev->device == 0x0003) -+ msleep(NVME_QUIRK_DELAY_AMOUNT); -+ - return nvme_wait_ready(dev, cap, false); - } - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 655f79db7899..58048dd5fcd0 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -632,9 +632,12 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, - const char *pathp; - int offset, rc = 0, depth = -1; - -- for (offset = fdt_next_node(blob, -1, &depth); -- offset >= 0 && depth >= 0 && !rc; -- offset = fdt_next_node(blob, offset, &depth)) { -+ if (!blob) -+ return 0; -+ -+ for (offset = fdt_next_node(blob, -1, &depth); -+ offset >= 0 && depth >= 0 && !rc; -+ offset = fdt_next_node(blob, offset, &depth)) { - - pathp = fdt_get_name(blob, offset, NULL); - if (*pathp == '/') -diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c -index 200d3de8bc1e..a180c000e246 100644 ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -1112,6 +1112,18 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, - */ - if (dump_payload) - goto after_immediate_data; -+ /* -+ * Check for underflow case where both EDTL and immediate data payload -+ * exceeds what is presented by CDB's TRANSFER LENGTH, and what has -+ * already been set in target_cmd_size_check() as se_cmd->data_length. -+ * -+ * For this special case, fail the command and dump the immediate data -+ * payload. -+ */ -+ if (cmd->first_burst_len > cmd->se_cmd.data_length) { -+ cmd->sense_reason = TCM_INVALID_CDB_FIELD; -+ goto after_immediate_data; -+ } - - immed_ret = iscsit_handle_immediate_data(cmd, hdr, - cmd->first_burst_len); -diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h -index 253a91bff943..272e6f755322 100644 ---- a/drivers/target/target_core_internal.h -+++ b/drivers/target/target_core_internal.h -@@ -132,7 +132,7 @@ int init_se_kmem_caches(void); - void release_se_kmem_caches(void); - u32 scsi_get_new_index(scsi_index_t); - void transport_subsystem_check_init(void); --void transport_cmd_finish_abort(struct se_cmd *, int); -+int transport_cmd_finish_abort(struct se_cmd *, int); - unsigned char *transport_dump_cmd_direction(struct se_cmd *); - void transport_dump_dev_state(struct se_device *, char *, int *); - void transport_dump_dev_info(struct se_device *, struct se_lun *, -diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c -index 46b1991fbb50..c9be953496ec 100644 ---- a/drivers/target/target_core_tmr.c -+++ b/drivers/target/target_core_tmr.c -@@ -75,7 +75,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr) - kfree(tmr); - } - --static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas) -+static int core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas) - { - unsigned long flags; - bool remove = true, send_tas; -@@ -91,7 +91,7 @@ static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas) - transport_send_task_abort(cmd); - } - -- transport_cmd_finish_abort(cmd, remove); -+ return transport_cmd_finish_abort(cmd, remove); - } - - static int target_check_cdb_and_preempt(struct list_head *list, -@@ -185,8 +185,8 @@ void core_tmr_abort_task( - cancel_work_sync(&se_cmd->work); - transport_wait_for_tasks(se_cmd); - -- transport_cmd_finish_abort(se_cmd, true); -- target_put_sess_cmd(se_cmd); -+ if (!transport_cmd_finish_abort(se_cmd, true)) -+ target_put_sess_cmd(se_cmd); - - printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" - " ref_tag: %llu\n", ref_tag); -@@ -286,8 +286,8 @@ static void core_tmr_drain_tmr_list( - cancel_work_sync(&cmd->work); - transport_wait_for_tasks(cmd); - -- transport_cmd_finish_abort(cmd, 1); -- target_put_sess_cmd(cmd); -+ if (!transport_cmd_finish_abort(cmd, 1)) -+ target_put_sess_cmd(cmd); - } - } - -@@ -385,8 +385,8 @@ static void core_tmr_drain_state_list( - cancel_work_sync(&cmd->work); - transport_wait_for_tasks(cmd); - -- core_tmr_handle_tas_abort(cmd, tas); -- target_put_sess_cmd(cmd); -+ if (!core_tmr_handle_tas_abort(cmd, tas)) -+ target_put_sess_cmd(cmd); - } - } - -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index 60743bf27f37..37c77db6e737 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -639,9 +639,10 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) - percpu_ref_put(&lun->lun_ref); - } - --void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) -+int transport_cmd_finish_abort(struct se_cmd *cmd, int remove) - { - bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF); -+ int ret = 0; - - if (cmd->se_cmd_flags & SCF_SE_LUN_CMD) - transport_lun_remove_cmd(cmd); -@@ -653,9 +654,11 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) - cmd->se_tfo->aborted_task(cmd); - - if (transport_cmd_check_stop_to_fabric(cmd)) -- return; -+ return 1; - if (remove && ack_kref) -- transport_put_cmd(cmd); -+ ret = transport_put_cmd(cmd); -+ -+ return ret; - } - - static void target_complete_failure_work(struct work_struct *work) -diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c -index 9ad5145d3103..6d8f865a2fb7 100644 ---- a/drivers/usb/gadget/function/f_fs.c -+++ b/drivers/usb/gadget/function/f_fs.c -@@ -1668,12 +1668,12 @@ static int ffs_func_eps_enable(struct ffs_function *func) - ep->ep->driver_data = ep; - ep->ep->desc = ds; - -- comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + -- USB_DT_ENDPOINT_SIZE); -- ep->ep->maxburst = comp_desc->bMaxBurst + 1; -- -- if (needs_comp_desc) -+ if (needs_comp_desc) { -+ comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds + -+ USB_DT_ENDPOINT_SIZE); -+ ep->ep->maxburst = comp_desc->bMaxBurst + 1; - ep->ep->comp_desc = comp_desc; -+ } - - ret = usb_ep_enable(ep->ep); - if (likely(!ret)) { -diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c -index 7fbe19d5279e..81b2b9f808b5 100644 ---- a/drivers/usb/usbip/vhci_hcd.c -+++ b/drivers/usb/usbip/vhci_hcd.c -@@ -215,14 +215,19 @@ done: - - static inline void hub_descriptor(struct usb_hub_descriptor *desc) - { -+ int width; -+ - memset(desc, 0, sizeof(*desc)); - desc->bDescriptorType = USB_DT_HUB; -- desc->bDescLength = 9; - desc->wHubCharacteristics = cpu_to_le16( - HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM); -+ - desc->bNbrPorts = VHCI_NPORTS; -- desc->u.hs.DeviceRemovable[0] = 0xff; -- desc->u.hs.DeviceRemovable[1] = 0xff; -+ BUILD_BUG_ON(VHCI_NPORTS > USB_MAXCHILDREN); -+ width = desc->bNbrPorts / 8 + 1; -+ desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width; -+ memset(&desc->u.hs.DeviceRemovable[0], 0, width); -+ memset(&desc->u.hs.DeviceRemovable[width], 0xff, width); - } - - static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, -diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c -index ac7d921ed984..257425511d10 100644 ---- a/fs/autofs4/dev-ioctl.c -+++ b/fs/autofs4/dev-ioctl.c -@@ -331,7 +331,7 @@ static int autofs_dev_ioctl_fail(struct file *fp, - int status; - - token = (autofs_wqt_t) param->fail.token; -- status = param->fail.status ? param->fail.status : -ENOENT; -+ status = param->fail.status < 0 ? param->fail.status : -ENOENT; - return autofs4_wait_release(sbi, token, status); - } - -diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c -index 87b87e091e8e..efd72e1fae74 100644 ---- a/fs/cifs/smb1ops.c -+++ b/fs/cifs/smb1ops.c -@@ -849,8 +849,13 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_fid *fid, __u16 search_flags, - struct cifs_search_info *srch_inf) - { -- return CIFSFindFirst(xid, tcon, path, cifs_sb, -- &fid->netfid, search_flags, srch_inf, true); -+ int rc; -+ -+ rc = CIFSFindFirst(xid, tcon, path, cifs_sb, -+ &fid->netfid, search_flags, srch_inf, true); -+ if (rc) -+ cifs_dbg(FYI, "find first failed=%d\n", rc); -+ return rc; - } - - static int -diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c -index 087918c4612a..1d125d3d0d89 100644 ---- a/fs/cifs/smb2ops.c -+++ b/fs/cifs/smb2ops.c -@@ -909,7 +909,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); - kfree(utf16_path); - if (rc) { -- cifs_dbg(VFS, "open dir failed\n"); -+ cifs_dbg(FYI, "open dir failed rc=%d\n", rc); - return rc; - } - -@@ -919,7 +919,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - rc = SMB2_query_directory(xid, tcon, fid->persistent_fid, - fid->volatile_fid, 0, srch_inf); - if (rc) { -- cifs_dbg(VFS, "query directory failed\n"); -+ cifs_dbg(FYI, "query directory failed rc=%d\n", rc); - SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); - } - return rc; -diff --git a/fs/exec.c b/fs/exec.c -index 3a6de10d3891..02153068a694 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -206,8 +206,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, - - if (write) { - unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; -+ unsigned long ptr_size; - struct rlimit *rlim; - -+ /* -+ * Since the stack will hold pointers to the strings, we -+ * must account for them as well. -+ * -+ * The size calculation is the entire vma while each arg page is -+ * built, so each time we get here it's calculating how far it -+ * is currently (rather than each call being just the newly -+ * added size from the arg page). As a result, we need to -+ * always add the entire size of the pointers, so that on the -+ * last call to get_arg_page() we'll actually have the entire -+ * correct size. -+ */ -+ ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); -+ if (ptr_size > ULONG_MAX - size) -+ goto fail; -+ size += ptr_size; -+ - acct_arg_size(bprm, size / PAGE_SIZE); - - /* -@@ -225,13 +243,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, - * to work from. - */ - rlim = current->signal->rlim; -- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { -- put_page(page); -- return NULL; -- } -+ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) -+ goto fail; - } - - return page; -+ -+fail: -+ put_page(page); -+ return NULL; - } - - static void put_arg_page(struct page *page) -diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h -index 25247220b4b7..f0f1793cfa49 100644 ---- a/include/linux/timekeeper_internal.h -+++ b/include/linux/timekeeper_internal.h -@@ -29,7 +29,6 @@ - */ - struct tk_read_base { - struct clocksource *clock; -- cycle_t (*read)(struct clocksource *cs); - cycle_t mask; - cycle_t cycle_last; - u32 mult; -diff --git a/kernel/signal.c b/kernel/signal.c -index f3f1f7a972fd..b92a047ddc82 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -503,7 +503,8 @@ int unhandled_signal(struct task_struct *tsk, int sig) - return !tsk->ptrace; - } - --static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) -+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info, -+ bool *resched_timer) - { - struct sigqueue *q, *first = NULL; - -@@ -525,6 +526,12 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) - still_pending: - list_del_init(&first->list); - copy_siginfo(info, &first->info); -+ -+ *resched_timer = -+ (first->flags & SIGQUEUE_PREALLOC) && -+ (info->si_code == SI_TIMER) && -+ (info->si_sys_private); -+ - __sigqueue_free(first); - } else { - /* -@@ -541,12 +548,12 @@ still_pending: - } - - static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, -- siginfo_t *info) -+ siginfo_t *info, bool *resched_timer) - { - int sig = next_signal(pending, mask); - - if (sig) -- collect_signal(sig, pending, info); -+ collect_signal(sig, pending, info, resched_timer); - return sig; - } - -@@ -558,15 +565,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, - */ - int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) - { -+ bool resched_timer = false; - int signr; - - /* We only dequeue private signals from ourselves, we don't let - * signalfd steal them - */ -- signr = __dequeue_signal(&tsk->pending, mask, info); -+ signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer); - if (!signr) { - signr = __dequeue_signal(&tsk->signal->shared_pending, -- mask, info); -+ mask, info, &resched_timer); - /* - * itimer signal ? - * -@@ -611,7 +619,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) - */ - current->jobctl |= JOBCTL_STOP_DEQUEUED; - } -- if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { -+ if (resched_timer) { - /* - * Release the siglock to ensure proper locking order - * of timer locks outside of siglocks. Note, we leave -diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c -index 738012d68117..6e4866834d26 100644 ---- a/kernel/time/timekeeping.c -+++ b/kernel/time/timekeeping.c -@@ -116,6 +116,26 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) - tk->offs_boot = ktime_add(tk->offs_boot, delta); - } - -+/* -+ * tk_clock_read - atomic clocksource read() helper -+ * -+ * This helper is necessary to use in the read paths because, while the -+ * seqlock ensures we don't return a bad value while structures are updated, -+ * it doesn't protect from potential crashes. There is the possibility that -+ * the tkr's clocksource may change between the read reference, and the -+ * clock reference passed to the read function. This can cause crashes if -+ * the wrong clocksource is passed to the wrong read function. -+ * This isn't necessary to use when holding the timekeeper_lock or doing -+ * a read of the fast-timekeeper tkrs (which is protected by its own locking -+ * and update logic). -+ */ -+static inline u64 tk_clock_read(struct tk_read_base *tkr) -+{ -+ struct clocksource *clock = READ_ONCE(tkr->clock); -+ -+ return clock->read(clock); -+} -+ - #ifdef CONFIG_DEBUG_TIMEKEEPING - #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */ - -@@ -173,7 +193,7 @@ static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr) - */ - do { - seq = read_seqcount_begin(&tk_core.seq); -- now = tkr->read(tkr->clock); -+ now = tk_clock_read(tkr); - last = tkr->cycle_last; - mask = tkr->mask; - max = tkr->clock->max_cycles; -@@ -207,7 +227,7 @@ static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr) - cycle_t cycle_now, delta; - - /* read clocksource */ -- cycle_now = tkr->read(tkr->clock); -+ cycle_now = tk_clock_read(tkr); - - /* calculate the delta since the last update_wall_time */ - delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); -@@ -235,12 +255,10 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock) - - old_clock = tk->tkr_mono.clock; - tk->tkr_mono.clock = clock; -- tk->tkr_mono.read = clock->read; - tk->tkr_mono.mask = clock->mask; -- tk->tkr_mono.cycle_last = tk->tkr_mono.read(clock); -+ tk->tkr_mono.cycle_last = tk_clock_read(&tk->tkr_mono); - - tk->tkr_raw.clock = clock; -- tk->tkr_raw.read = clock->read; - tk->tkr_raw.mask = clock->mask; - tk->tkr_raw.cycle_last = tk->tkr_mono.cycle_last; - -@@ -404,7 +422,7 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf) - - now += timekeeping_delta_to_ns(tkr, - clocksource_delta( -- tkr->read(tkr->clock), -+ tk_clock_read(tkr), - tkr->cycle_last, - tkr->mask)); - } while (read_seqcount_retry(&tkf->seq, seq)); -@@ -432,6 +450,10 @@ static cycle_t dummy_clock_read(struct clocksource *cs) - return cycles_at_suspend; - } - -+static struct clocksource dummy_clock = { -+ .read = dummy_clock_read, -+}; -+ - /** - * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. - * @tk: Timekeeper to snapshot. -@@ -448,13 +470,13 @@ static void halt_fast_timekeeper(struct timekeeper *tk) - struct tk_read_base *tkr = &tk->tkr_mono; - - memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); -- cycles_at_suspend = tkr->read(tkr->clock); -- tkr_dummy.read = dummy_clock_read; -+ cycles_at_suspend = tk_clock_read(tkr); -+ tkr_dummy.clock = &dummy_clock; - update_fast_timekeeper(&tkr_dummy, &tk_fast_mono); - - tkr = &tk->tkr_raw; - memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); -- tkr_dummy.read = dummy_clock_read; -+ tkr_dummy.clock = &dummy_clock; - update_fast_timekeeper(&tkr_dummy, &tk_fast_raw); - } - -@@ -618,11 +640,10 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action) - */ - static void timekeeping_forward_now(struct timekeeper *tk) - { -- struct clocksource *clock = tk->tkr_mono.clock; - cycle_t cycle_now, delta; - s64 nsec; - -- cycle_now = tk->tkr_mono.read(clock); -+ cycle_now = tk_clock_read(&tk->tkr_mono); - delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask); - tk->tkr_mono.cycle_last = cycle_now; - tk->tkr_raw.cycle_last = cycle_now; -@@ -1405,7 +1426,7 @@ void timekeeping_resume(void) - * The less preferred source will only be tried if there is no better - * usable source. The rtc part is handled separately in rtc core code. - */ -- cycle_now = tk->tkr_mono.read(clock); -+ cycle_now = tk_clock_read(&tk->tkr_mono); - if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) && - cycle_now > tk->tkr_mono.cycle_last) { - u64 num, max = ULLONG_MAX; -@@ -1800,7 +1821,7 @@ void update_wall_time(void) - #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET - offset = real_tk->cycle_interval; - #else -- offset = clocksource_delta(tk->tkr_mono.read(tk->tkr_mono.clock), -+ offset = clocksource_delta(tk_clock_read(&tk->tkr_mono), - tk->tkr_mono.cycle_last, tk->tkr_mono.mask); - #endif - -diff --git a/lib/cmdline.c b/lib/cmdline.c -index 8f13cf73c2ec..79069d7938ea 100644 ---- a/lib/cmdline.c -+++ b/lib/cmdline.c -@@ -22,14 +22,14 @@ - * the values[M, M+1, ..., N] into the ints array in get_options. - */ - --static int get_range(char **str, int *pint) -+static int get_range(char **str, int *pint, int n) - { - int x, inc_counter, upper_range; - - (*str)++; - upper_range = simple_strtol((*str), NULL, 0); - inc_counter = upper_range - *pint; -- for (x = *pint; x < upper_range; x++) -+ for (x = *pint; n && x < upper_range; x++, n--) - *pint++ = x; - return inc_counter; - } -@@ -96,7 +96,7 @@ char *get_options(const char *str, int nints, int *ints) - break; - if (res == 3) { - int range_nums; -- range_nums = get_range((char **)&str, ints + i); -+ range_nums = get_range((char **)&str, ints + i, nints - i); - if (range_nums < 0) - break; - /* -diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c -index da3cc09f683e..91d43ab3a961 100644 ---- a/net/rxrpc/ar-key.c -+++ b/net/rxrpc/ar-key.c -@@ -215,7 +215,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, - unsigned int *_toklen) - { - const __be32 *xdr = *_xdr; -- unsigned int toklen = *_toklen, n_parts, loop, tmp; -+ unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen; - - /* there must be at least one name, and at least #names+1 length - * words */ -@@ -245,16 +245,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, - toklen -= 4; - if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) - return -EINVAL; -- if (tmp > toklen) -+ paddedlen = (tmp + 3) & ~3; -+ if (paddedlen > toklen) - return -EINVAL; - princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); - if (!princ->name_parts[loop]) - return -ENOMEM; - memcpy(princ->name_parts[loop], xdr, tmp); - princ->name_parts[loop][tmp] = 0; -- tmp = (tmp + 3) & ~3; -- toklen -= tmp; -- xdr += tmp >> 2; -+ toklen -= paddedlen; -+ xdr += paddedlen >> 2; - } - - if (toklen < 4) -@@ -263,16 +263,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, - toklen -= 4; - if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) - return -EINVAL; -- if (tmp > toklen) -+ paddedlen = (tmp + 3) & ~3; -+ if (paddedlen > toklen) - return -EINVAL; - princ->realm = kmalloc(tmp + 1, GFP_KERNEL); - if (!princ->realm) - return -ENOMEM; - memcpy(princ->realm, xdr, tmp); - princ->realm[tmp] = 0; -- tmp = (tmp + 3) & ~3; -- toklen -= tmp; -- xdr += tmp >> 2; -+ toklen -= paddedlen; -+ xdr += paddedlen >> 2; - - _debug("%s/...@%s", princ->name_parts[0], princ->realm); - -@@ -291,7 +291,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, - unsigned int *_toklen) - { - const __be32 *xdr = *_xdr; -- unsigned int toklen = *_toklen, len; -+ unsigned int toklen = *_toklen, len, paddedlen; - - /* there must be at least one tag and one length word */ - if (toklen <= 8) -@@ -305,15 +305,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, - toklen -= 8; - if (len > max_data_size) - return -EINVAL; -+ paddedlen = (len + 3) & ~3; -+ if (paddedlen > toklen) -+ return -EINVAL; - td->data_len = len; - - if (len > 0) { - td->data = kmemdup(xdr, len, GFP_KERNEL); - if (!td->data) - return -ENOMEM; -- len = (len + 3) & ~3; -- toklen -= len; -- xdr += len >> 2; -+ toklen -= paddedlen; -+ xdr += paddedlen >> 2; - } - - _debug("tag %x len %x", td->tag, td->data_len); -@@ -385,7 +387,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, - const __be32 **_xdr, unsigned int *_toklen) - { - const __be32 *xdr = *_xdr; -- unsigned int toklen = *_toklen, len; -+ unsigned int toklen = *_toklen, len, paddedlen; - - /* there must be at least one length word */ - if (toklen <= 4) -@@ -397,6 +399,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, - toklen -= 4; - if (len > AFSTOKEN_K5_TIX_MAX) - return -EINVAL; -+ paddedlen = (len + 3) & ~3; -+ if (paddedlen > toklen) -+ return -EINVAL; - *_tktlen = len; - - _debug("ticket len %u", len); -@@ -405,9 +410,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, - *_ticket = kmemdup(xdr, len, GFP_KERNEL); - if (!*_ticket) - return -ENOMEM; -- len = (len + 3) & ~3; -- toklen -= len; -- xdr += len >> 2; -+ toklen -= paddedlen; -+ xdr += paddedlen >> 2; - } - - *_xdr = xdr; -@@ -550,7 +554,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) - { - const __be32 *xdr = prep->data, *token; - const char *cp; -- unsigned int len, tmp, loop, ntoken, toklen, sec_ix; -+ unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; - size_t datalen = prep->datalen; - int ret; - -@@ -576,22 +580,21 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) - if (len < 1 || len > AFSTOKEN_CELL_MAX) - goto not_xdr; - datalen -= 4; -- tmp = (len + 3) & ~3; -- if (tmp > datalen) -+ paddedlen = (len + 3) & ~3; -+ if (paddedlen > datalen) - goto not_xdr; - - cp = (const char *) xdr; - for (loop = 0; loop < len; loop++) - if (!isprint(cp[loop])) - goto not_xdr; -- if (len < tmp) -- for (; loop < tmp; loop++) -- if (cp[loop]) -- goto not_xdr; -+ for (; loop < paddedlen; loop++) -+ if (cp[loop]) -+ goto not_xdr; - _debug("cellname: [%u/%u] '%*.*s'", -- len, tmp, len, len, (const char *) xdr); -- datalen -= tmp; -- xdr += tmp >> 2; -+ len, paddedlen, len, len, (const char *) xdr); -+ datalen -= paddedlen; -+ xdr += paddedlen >> 2; - - /* get the token count */ - if (datalen < 12) -@@ -612,10 +615,11 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) - sec_ix = ntohl(*xdr); - datalen -= 4; - _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); -- if (toklen < 20 || toklen > datalen) -+ paddedlen = (toklen + 3) & ~3; -+ if (toklen < 20 || toklen > datalen || paddedlen > datalen) - goto not_xdr; -- datalen -= (toklen + 3) & ~3; -- xdr += (toklen + 3) >> 2; -+ datalen -= paddedlen; -+ xdr += paddedlen >> 2; - - } while (--loop > 0); - diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.75-76.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.75-76.patch deleted file mode 100644 index 29998d32a..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.75-76.patch +++ /dev/null @@ -1,2827 +0,0 @@ -diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt -index af70d1541d3a..be61d53e997f 100644 ---- a/Documentation/sysctl/kernel.txt -+++ b/Documentation/sysctl/kernel.txt -@@ -810,14 +810,13 @@ via the /proc/sys interface: - Each write syscall must fully contain the sysctl value to be - written, and multiple writes on the same sysctl file descriptor - will rewrite the sysctl value, regardless of file position. -- 0 - (default) Same behavior as above, but warn about processes that -- perform writes to a sysctl file descriptor when the file position -- is not 0. -- 1 - Respect file position when writing sysctl strings. Multiple writes -- will append to the sysctl value buffer. Anything past the max length -- of the sysctl value buffer will be ignored. Writes to numeric sysctl -- entries must always be at file position 0 and the value must be -- fully contained in the buffer sent in the write syscall. -+ 0 - Same behavior as above, but warn about processes that perform writes -+ to a sysctl file descriptor when the file position is not 0. -+ 1 - (default) Respect file position when writing sysctl strings. Multiple -+ writes will append to the sysctl value buffer. Anything past the max -+ length of the sysctl value buffer will be ignored. Writes to numeric -+ sysctl entries must always be at file position 0 and the value must -+ be fully contained in the buffer sent in the write syscall. - - ============================================================== - -diff --git a/Makefile b/Makefile -index 696d15d8ad5d..902ab134446e 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 75 -+SUBLEVEL = 76 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi -index 6f50f672efbd..de8ac998604d 100644 ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -54,14 +54,14 @@ - timer@0200 { - compatible = "arm,cortex-a9-global-timer"; - reg = <0x0200 0x100>; -- interrupts = ; -+ interrupts = ; - clocks = <&clk_periph>; - }; - - local-timer@0600 { - compatible = "arm,cortex-a9-twd-timer"; - reg = <0x0600 0x100>; -- interrupts = ; -+ interrupts = ; - clocks = <&clk_periph>; - }; - -diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c -index 4867f5daf82c..e47cffd25c6c 100644 ---- a/arch/arm/mm/mmu.c -+++ b/arch/arm/mm/mmu.c -@@ -1184,15 +1184,15 @@ void __init sanity_check_meminfo(void) - - high_memory = __va(arm_lowmem_limit - 1) + 1; - -+ if (!memblock_limit) -+ memblock_limit = arm_lowmem_limit; -+ - /* - * Round the memblock limit down to a pmd size. This - * helps to ensure that we will allocate memory from the - * last full pmd, which should be mapped. - */ -- if (memblock_limit) -- memblock_limit = round_down(memblock_limit, PMD_SIZE); -- if (!memblock_limit) -- memblock_limit = arm_lowmem_limit; -+ memblock_limit = round_down(memblock_limit, PMD_SIZE); - - memblock_set_current_limit(memblock_limit); - } -diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h -index caafd63b8092..40d1351e7573 100644 ---- a/arch/arm64/include/asm/acpi.h -+++ b/arch/arm64/include/asm/acpi.h -@@ -22,9 +22,9 @@ - #define ACPI_MADT_GICC_LENGTH \ - (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) - --#define BAD_MADT_GICC_ENTRY(entry, end) \ -- (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ -- (entry)->header.length != ACPI_MADT_GICC_LENGTH) -+#define BAD_MADT_GICC_ENTRY(entry, end) \ -+ (!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH || \ -+ (unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end)) - - /* Basic configuration for ACPI */ - #ifdef CONFIG_ACPI -diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c -index 3cedd1f95e0f..8ae4067a5eda 100644 ---- a/arch/mips/ath79/common.c -+++ b/arch/mips/ath79/common.c -@@ -76,14 +76,14 @@ void ath79_ddr_set_pci_windows(void) - { - BUG_ON(!ath79_ddr_pci_win_base); - -- __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0); -- __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1); -- __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2); -- __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3); -- __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4); -- __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5); -- __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6); -- __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7); -+ __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0); -+ __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4); -+ __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8); -+ __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc); -+ __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10); -+ __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14); -+ __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18); -+ __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c); - } - EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); - -diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S -index 7791840cf22c..db07793f7b43 100644 ---- a/arch/mips/kernel/entry.S -+++ b/arch/mips/kernel/entry.S -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -137,6 +138,7 @@ work_pending: - andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS - beqz t0, work_notifysig - work_resched: -+ TRACE_IRQS_OFF - jal schedule - - local_irq_disable # make sure need_resched and -@@ -173,6 +175,7 @@ syscall_exit_work: - beqz t0, work_pending # trace bit set? - local_irq_enable # could let syscall_trace_leave() - # call schedule() instead -+ TRACE_IRQS_ON - move a0, sp - jal syscall_trace_leave - b resume_userspace -diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c -index f63a289977cc..0b3e58a3189f 100644 ---- a/arch/mips/kernel/pm-cps.c -+++ b/arch/mips/kernel/pm-cps.c -@@ -55,7 +55,6 @@ DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT); - * state. Actually per-core rather than per-CPU. - */ - static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); --static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc); - - /* Indicates online CPUs coupled with the current CPU */ - static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); -@@ -625,7 +624,6 @@ static int __init cps_gen_core_entries(unsigned cpu) - { - enum cps_pm_state state; - unsigned core = cpu_data[cpu].core; -- unsigned dlinesz = cpu_data[cpu].dcache.linesz; - void *entry_fn, *core_rc; - - for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { -@@ -645,16 +643,11 @@ static int __init cps_gen_core_entries(unsigned cpu) - } - - if (!per_cpu(ready_count, core)) { -- core_rc = kmalloc(dlinesz * 2, GFP_KERNEL); -+ core_rc = kmalloc(sizeof(u32), GFP_KERNEL); - if (!core_rc) { - pr_err("Failed allocate core %u ready_count\n", core); - return -ENOMEM; - } -- per_cpu(ready_count_alloc, core) = core_rc; -- -- /* Ensure ready_count is aligned to a cacheline boundary */ -- core_rc += dlinesz - 1; -- core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1)); - per_cpu(ready_count, core) = core_rc; - } - -diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c -index 99a402231f4d..31ca2edd7218 100644 ---- a/arch/mips/kernel/traps.c -+++ b/arch/mips/kernel/traps.c -@@ -194,6 +194,8 @@ void show_stack(struct task_struct *task, unsigned long *sp) - { - struct pt_regs regs; - mm_segment_t old_fs = get_fs(); -+ -+ regs.cp0_status = KSU_KERNEL; - if (sp) { - regs.regs[29] = (unsigned long)sp; - regs.regs[31] = 0; -diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c -index dfb04fcedb04..48d6349fd9d7 100644 ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -107,31 +107,31 @@ static struct rt2880_pmx_group mt7620a_pinmux_data[] = { - }; - - static struct rt2880_pmx_func pwm1_grp_mt7628[] = { -- FUNC("sdcx", 3, 19, 1), -+ FUNC("sdxc d6", 3, 19, 1), - FUNC("utif", 2, 19, 1), - FUNC("gpio", 1, 19, 1), -- FUNC("pwm", 0, 19, 1), -+ FUNC("pwm1", 0, 19, 1), - }; - - static struct rt2880_pmx_func pwm0_grp_mt7628[] = { -- FUNC("sdcx", 3, 18, 1), -+ FUNC("sdxc d7", 3, 18, 1), - FUNC("utif", 2, 18, 1), - FUNC("gpio", 1, 18, 1), -- FUNC("pwm", 0, 18, 1), -+ FUNC("pwm0", 0, 18, 1), - }; - - static struct rt2880_pmx_func uart2_grp_mt7628[] = { -- FUNC("sdcx", 3, 20, 2), -+ FUNC("sdxc d5 d4", 3, 20, 2), - FUNC("pwm", 2, 20, 2), - FUNC("gpio", 1, 20, 2), -- FUNC("uart", 0, 20, 2), -+ FUNC("uart2", 0, 20, 2), - }; - - static struct rt2880_pmx_func uart1_grp_mt7628[] = { -- FUNC("sdcx", 3, 45, 2), -+ FUNC("sw_r", 3, 45, 2), - FUNC("pwm", 2, 45, 2), - FUNC("gpio", 1, 45, 2), -- FUNC("uart", 0, 45, 2), -+ FUNC("uart1", 0, 45, 2), - }; - - static struct rt2880_pmx_func i2c_grp_mt7628[] = { -@@ -143,21 +143,21 @@ static struct rt2880_pmx_func i2c_grp_mt7628[] = { - - static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) }; - static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) }; --static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 15, 38) }; -+static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) }; - static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; - - static struct rt2880_pmx_func sd_mode_grp_mt7628[] = { - FUNC("jtag", 3, 22, 8), - FUNC("utif", 2, 22, 8), - FUNC("gpio", 1, 22, 8), -- FUNC("sdcx", 0, 22, 8), -+ FUNC("sdxc", 0, 22, 8), - }; - - static struct rt2880_pmx_func uart0_grp_mt7628[] = { - FUNC("-", 3, 12, 2), - FUNC("-", 2, 12, 2), - FUNC("gpio", 1, 12, 2), -- FUNC("uart", 0, 12, 2), -+ FUNC("uart0", 0, 12, 2), - }; - - static struct rt2880_pmx_func i2s_grp_mt7628[] = { -@@ -171,7 +171,7 @@ static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = { - FUNC("-", 3, 6, 1), - FUNC("refclk", 2, 6, 1), - FUNC("gpio", 1, 6, 1), -- FUNC("spi", 0, 6, 1), -+ FUNC("spi cs1", 0, 6, 1), - }; - - static struct rt2880_pmx_func spis_grp_mt7628[] = { -@@ -188,28 +188,44 @@ static struct rt2880_pmx_func gpio_grp_mt7628[] = { - FUNC("gpio", 0, 11, 1), - }; - --#define MT7628_GPIO_MODE_MASK 0x3 -- --#define MT7628_GPIO_MODE_PWM1 30 --#define MT7628_GPIO_MODE_PWM0 28 --#define MT7628_GPIO_MODE_UART2 26 --#define MT7628_GPIO_MODE_UART1 24 --#define MT7628_GPIO_MODE_I2C 20 --#define MT7628_GPIO_MODE_REFCLK 18 --#define MT7628_GPIO_MODE_PERST 16 --#define MT7628_GPIO_MODE_WDT 14 --#define MT7628_GPIO_MODE_SPI 12 --#define MT7628_GPIO_MODE_SDMODE 10 --#define MT7628_GPIO_MODE_UART0 8 --#define MT7628_GPIO_MODE_I2S 6 --#define MT7628_GPIO_MODE_CS1 4 --#define MT7628_GPIO_MODE_SPIS 2 --#define MT7628_GPIO_MODE_GPIO 0 -+static struct rt2880_pmx_func wled_kn_grp_mt7628[] = { -+ FUNC("rsvd", 3, 35, 1), -+ FUNC("rsvd", 2, 35, 1), -+ FUNC("gpio", 1, 35, 1), -+ FUNC("wled_kn", 0, 35, 1), -+}; -+ -+static struct rt2880_pmx_func wled_an_grp_mt7628[] = { -+ FUNC("rsvd", 3, 44, 1), -+ FUNC("rsvd", 2, 44, 1), -+ FUNC("gpio", 1, 44, 1), -+ FUNC("wled_an", 0, 44, 1), -+}; -+ -+#define MT7628_GPIO_MODE_MASK 0x3 -+ -+#define MT7628_GPIO_MODE_WLED_KN 48 -+#define MT7628_GPIO_MODE_WLED_AN 32 -+#define MT7628_GPIO_MODE_PWM1 30 -+#define MT7628_GPIO_MODE_PWM0 28 -+#define MT7628_GPIO_MODE_UART2 26 -+#define MT7628_GPIO_MODE_UART1 24 -+#define MT7628_GPIO_MODE_I2C 20 -+#define MT7628_GPIO_MODE_REFCLK 18 -+#define MT7628_GPIO_MODE_PERST 16 -+#define MT7628_GPIO_MODE_WDT 14 -+#define MT7628_GPIO_MODE_SPI 12 -+#define MT7628_GPIO_MODE_SDMODE 10 -+#define MT7628_GPIO_MODE_UART0 8 -+#define MT7628_GPIO_MODE_I2S 6 -+#define MT7628_GPIO_MODE_CS1 4 -+#define MT7628_GPIO_MODE_SPIS 2 -+#define MT7628_GPIO_MODE_GPIO 0 - - static struct rt2880_pmx_group mt7628an_pinmux_data[] = { -- GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, -+ GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_PWM1), -- GRP_G("pmw1", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, -+ GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_PWM0), - GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_UART2), -@@ -233,6 +249,10 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = { - 1, MT7628_GPIO_MODE_SPIS), - GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_GPIO), -+ GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK, -+ 1, MT7628_GPIO_MODE_WLED_AN), -+ GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, -+ 1, MT7628_GPIO_MODE_WLED_KN), - { 0 } - }; - -@@ -439,7 +459,7 @@ void __init ralink_clk_init(void) - ralink_clk_add("10000c00.uartlite", periph_rate); - ralink_clk_add("10180000.wmac", xtal_rate); - -- if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) { -+ if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) { - /* - * When the CPU goes into sleep mode, the BUS clock will be - * too low for USB to function properly. Adjust the busses -diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c -index 15506a1ff22a..9dd67749c592 100644 ---- a/arch/mips/ralink/rt288x.c -+++ b/arch/mips/ralink/rt288x.c -@@ -109,5 +109,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) - soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; - - rt2880_pinmux_data = rt2880_pinmux_data_act; -- ralink_soc == RT2880_SOC; -+ ralink_soc = RT2880_SOC; - } -diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c -index 98949b0df00a..6696c1986844 100644 ---- a/arch/powerpc/kernel/eeh.c -+++ b/arch/powerpc/kernel/eeh.c -@@ -304,9 +304,17 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity) - * - * For pHyp, we have to enable IO for log retrieval. Otherwise, - * 0xFF's is always returned from PCI config space. -+ * -+ * When the @severity is EEH_LOG_PERM, the PE is going to be -+ * removed. Prior to that, the drivers for devices included in -+ * the PE will be closed. The drivers rely on working IO path -+ * to bring the devices to quiet state. Otherwise, PCI traffic -+ * from those devices after they are removed is like to cause -+ * another unexpected EEH error. - */ - if (!(pe->type & EEH_PE_PHB)) { -- if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG)) -+ if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) || -+ severity == EEH_LOG_PERM) - eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); - - /* -diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h -index d7697ab802f6..8e136b88cdf4 100644 ---- a/arch/s390/include/asm/ctl_reg.h -+++ b/arch/s390/include/asm/ctl_reg.h -@@ -15,7 +15,9 @@ - BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ - asm volatile( \ - " lctlg %1,%2,%0\n" \ -- : : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\ -+ : \ -+ : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high) \ -+ : "memory"); \ - } - - #define __ctl_store(array, low, high) { \ -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index e9cd7befcb76..19d14ac23ef9 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -221,6 +221,9 @@ struct x86_emulate_ops { - void (*get_cpuid)(struct x86_emulate_ctxt *ctxt, - u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); - void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); -+ -+ unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); -+ void (*set_hflags)(struct x86_emulate_ctxt *ctxt, unsigned hflags); - }; - - typedef u32 __attribute__((vector_size(16))) sse128_t; -@@ -290,7 +293,6 @@ struct x86_emulate_ctxt { - - /* interruptibility state, as a result of execution of STI or MOV SS */ - int interruptibility; -- int emul_flags; - - bool perm_ok; /* do not check permissions if true */ - bool ud; /* inject an #UD if host doesn't support insn */ -diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c -index 1dcea225977d..04b2f3cad7ba 100644 ---- a/arch/x86/kvm/emulate.c -+++ b/arch/x86/kvm/emulate.c -@@ -2531,7 +2531,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) - u64 smbase; - int ret; - -- if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0) -+ if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0) - return emulate_ud(ctxt); - - /* -@@ -2580,11 +2580,11 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) - return X86EMUL_UNHANDLEABLE; - } - -- if ((ctxt->emul_flags & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) -+ if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) - ctxt->ops->set_nmi_mask(ctxt, false); - -- ctxt->emul_flags &= ~X86EMUL_SMM_INSIDE_NMI_MASK; -- ctxt->emul_flags &= ~X86EMUL_SMM_MASK; -+ ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) & -+ ~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK)); - return X86EMUL_CONTINUE; - } - -@@ -5296,6 +5296,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) - const struct x86_emulate_ops *ops = ctxt->ops; - int rc = X86EMUL_CONTINUE; - int saved_dst_type = ctxt->dst.type; -+ unsigned emul_flags; - - ctxt->mem_read.pos = 0; - -@@ -5310,6 +5311,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) - goto done; - } - -+ emul_flags = ctxt->ops->get_hflags(ctxt); - if (unlikely(ctxt->d & - (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) { - if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) || -@@ -5343,7 +5345,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) - fetch_possible_mmx_operand(ctxt, &ctxt->dst); - } - -- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { -+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_PRE_EXCEPT); - if (rc != X86EMUL_CONTINUE) -@@ -5372,7 +5374,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) - goto done; - } - -- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { -+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_POST_EXCEPT); - if (rc != X86EMUL_CONTINUE) -@@ -5426,7 +5428,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) - - special_insn: - -- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { -+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_POST_MEMACCESS); - if (rc != X86EMUL_CONTINUE) -diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c -index ab38af4f4947..23a7c7ba377a 100644 ---- a/arch/x86/kvm/pmu_intel.c -+++ b/arch/x86/kvm/pmu_intel.c -@@ -294,7 +294,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) - ((u64)1 << edx.split.bit_width_fixed) - 1; - } - -- pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) | -+ pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) | - (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED); - pmu->global_ctrl_mask = ~pmu->global_ctrl; - -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index 50ca8f409a7c..bbaa11f4e74b 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -2264,7 +2264,7 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned nr) - if (!(vmcs12->exception_bitmap & (1u << nr))) - return 0; - -- nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason, -+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, - vmcs_read32(VM_EXIT_INTR_INFO), - vmcs_readl(EXIT_QUALIFICATION)); - return 1; -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 6c82792487e9..8e526c6fd784 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -4844,6 +4844,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector, - - if (var.unusable) { - memset(desc, 0, sizeof(*desc)); -+ if (base3) -+ *base3 = 0; - return false; - } - -@@ -4999,6 +5001,16 @@ static void emulator_set_nmi_mask(struct x86_emulate_ctxt *ctxt, bool masked) - kvm_x86_ops->set_nmi_mask(emul_to_vcpu(ctxt), masked); - } - -+static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt) -+{ -+ return emul_to_vcpu(ctxt)->arch.hflags; -+} -+ -+static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags) -+{ -+ kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags); -+} -+ - static const struct x86_emulate_ops emulate_ops = { - .read_gpr = emulator_read_gpr, - .write_gpr = emulator_write_gpr, -@@ -5038,6 +5050,8 @@ static const struct x86_emulate_ops emulate_ops = { - .intercept = emulator_intercept, - .get_cpuid = emulator_get_cpuid, - .set_nmi_mask = emulator_set_nmi_mask, -+ .get_hflags = emulator_get_hflags, -+ .set_hflags = emulator_set_hflags, - }; - - static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask) -@@ -5090,7 +5104,6 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu) - BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK); - BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK); - BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK); -- ctxt->emul_flags = vcpu->arch.hflags; - - init_decode_cache(ctxt); - vcpu->arch.emulate_regs_need_sync_from_vcpu = false; -@@ -5486,8 +5499,6 @@ restart: - unsigned long rflags = kvm_x86_ops->get_rflags(vcpu); - toggle_interruptibility(vcpu, ctxt->interruptibility); - vcpu->arch.emulate_regs_need_sync_to_vcpu = false; -- if (vcpu->arch.hflags != ctxt->emul_flags) -- kvm_set_hflags(vcpu, ctxt->emul_flags); - kvm_rip_write(vcpu, ctxt->eip); - if (r == EMULATE_DONE) - kvm_vcpu_check_singlestep(vcpu, rflags, &r); -@@ -5974,7 +5985,8 @@ static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt) - - kvm_x86_ops->patch_hypercall(vcpu, instruction); - -- return emulator_write_emulated(ctxt, rip, instruction, 3, NULL); -+ return emulator_write_emulated(ctxt, rip, instruction, 3, -+ &ctxt->exception); - } - - static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu) -diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c -index ef05755a1900..7ed47b1e6f42 100644 ---- a/arch/x86/mm/mpx.c -+++ b/arch/x86/mm/mpx.c -@@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) - * We were not able to extract an address from the instruction, - * probably because there was something invalid in it. - */ -- if (info->si_addr == (void *)-1) { -+ if (info->si_addr == (void __user *)-1) { - err = -EINVAL; - goto err_out; - } -@@ -525,15 +525,7 @@ int mpx_handle_bd_fault(void) - if (!kernel_managing_mpx_tables(current->mm)) - return -EINVAL; - -- if (do_mpx_bt_fault()) { -- force_sig(SIGSEGV, current); -- /* -- * The force_sig() is essentially "handling" this -- * exception, so we do not pass up the error -- * from do_mpx_bt_fault(). -- */ -- } -- return 0; -+ return do_mpx_bt_fault(); - } - - /* -diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c -index 5fb6adaaa796..5a760fd66bec 100644 ---- a/arch/x86/mm/tlb.c -+++ b/arch/x86/mm/tlb.c -@@ -134,8 +134,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, - { - struct flush_tlb_info info; - -- if (end == 0) -- end = start + PAGE_SIZE; - info.flush_mm = mm; - info.flush_start = start; - info.flush_end = end; -@@ -264,7 +262,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) - } - - if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) -- flush_tlb_others(mm_cpumask(mm), mm, start, 0UL); -+ flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE); - - preempt_enable(); - } -diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c -index 9d359e05fad7..8161090a1970 100644 ---- a/block/blk-cgroup.c -+++ b/block/blk-cgroup.c -@@ -788,6 +788,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - { - struct gendisk *disk; - struct blkcg_gq *blkg; -+ struct module *owner; - unsigned int major, minor; - int key_len, part, ret; - char *body; -@@ -804,7 +805,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - if (!disk) - return -ENODEV; - if (part) { -+ owner = disk->fops->owner; - put_disk(disk); -+ module_put(owner); - return -ENODEV; - } - -@@ -820,7 +823,9 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - ret = PTR_ERR(blkg); - rcu_read_unlock(); - spin_unlock_irq(disk->queue->queue_lock); -+ owner = disk->fops->owner; - put_disk(disk); -+ module_put(owner); - /* - * If queue was bypassing, we should retry. Do so after a - * short msleep(). It isn't strictly necessary but queue -@@ -851,9 +856,13 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep); - void blkg_conf_finish(struct blkg_conf_ctx *ctx) - __releases(ctx->disk->queue->queue_lock) __releases(rcu) - { -+ struct module *owner; -+ - spin_unlock_irq(ctx->disk->queue->queue_lock); - rcu_read_unlock(); -+ owner = ctx->disk->fops->owner; - put_disk(ctx->disk); -+ module_put(owner); - } - EXPORT_SYMBOL_GPL(blkg_conf_finish); - -diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c -index 31e8ae916ba0..be0b09a0fb44 100644 ---- a/drivers/char/virtio_console.c -+++ b/drivers/char/virtio_console.c -@@ -1864,7 +1864,7 @@ static void config_work_handler(struct work_struct *work) - { - struct ports_device *portdev; - -- portdev = container_of(work, struct ports_device, control_work); -+ portdev = container_of(work, struct ports_device, config_work); - if (!use_multiport(portdev)) { - struct virtio_device *vdev; - struct port *port; -diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c -index d6d425773fa4..5b2db3c6568f 100644 ---- a/drivers/cpufreq/s3c2416-cpufreq.c -+++ b/drivers/cpufreq/s3c2416-cpufreq.c -@@ -400,7 +400,6 @@ static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) - rate = clk_get_rate(s3c_freq->hclk); - if (rate < 133 * 1000 * 1000) { - pr_err("cpufreq: HCLK not at 133MHz\n"); -- clk_put(s3c_freq->hclk); - ret = -EINVAL; - goto err_armclk; - } -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -index 25a3e2485cc2..2bc17a907ecf 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c -@@ -124,6 +124,13 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, - } - break; - } -+ -+ if (!(*out_ring && (*out_ring)->adev)) { -+ DRM_ERROR("Ring %d is not initialized on IP %d\n", -+ ring, ip_type); -+ return -EINVAL; -+ } -+ - return 0; - } - -diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h -index b92139e9b9d8..b5c64edeb668 100644 ---- a/drivers/gpu/drm/ast/ast_drv.h -+++ b/drivers/gpu/drm/ast/ast_drv.h -@@ -113,7 +113,11 @@ struct ast_private { - struct ttm_bo_kmap_obj cache_kmap; - int next_cursor; - bool support_wide_screen; -- bool DisableP2A; -+ enum { -+ ast_use_p2a, -+ ast_use_dt, -+ ast_use_defaults -+ } config_mode; - - enum ast_tx_chip tx_chip_type; - u8 dp501_maxclk; -diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c -index 6c021165ca67..498a94069e6b 100644 ---- a/drivers/gpu/drm/ast/ast_main.c -+++ b/drivers/gpu/drm/ast/ast_main.c -@@ -62,13 +62,84 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, - return ret; - } - -+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) -+{ -+ struct device_node *np = dev->pdev->dev.of_node; -+ struct ast_private *ast = dev->dev_private; -+ uint32_t data, jregd0, jregd1; -+ -+ /* Defaults */ -+ ast->config_mode = ast_use_defaults; -+ *scu_rev = 0xffffffff; -+ -+ /* Check if we have device-tree properties */ -+ if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", -+ scu_rev)) { -+ /* We do, disable P2A access */ -+ ast->config_mode = ast_use_dt; -+ DRM_INFO("Using device-tree for configuration\n"); -+ return; -+ } -+ -+ /* Not all families have a P2A bridge */ -+ if (dev->pdev->device != PCI_CHIP_AST2000) -+ return; -+ -+ /* -+ * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge -+ * is disabled. We force using P2A if VGA only mode bit -+ * is set D[7] -+ */ -+ jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); -+ jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); -+ if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { -+ /* Double check it's actually working */ -+ data = ast_read32(ast, 0xf004); -+ if (data != 0xFFFFFFFF) { -+ /* P2A works, grab silicon revision */ -+ ast->config_mode = ast_use_p2a; -+ -+ DRM_INFO("Using P2A bridge for configuration\n"); -+ -+ /* Read SCU7c (silicon revision register) */ -+ ast_write32(ast, 0xf004, 0x1e6e0000); -+ ast_write32(ast, 0xf000, 0x1); -+ *scu_rev = ast_read32(ast, 0x1207c); -+ return; -+ } -+ } -+ -+ /* We have a P2A bridge but it's disabled */ -+ DRM_INFO("P2A bridge disabled, using default configuration\n"); -+} - - static int ast_detect_chip(struct drm_device *dev, bool *need_post) - { - struct ast_private *ast = dev->dev_private; -- uint32_t data, jreg; -+ uint32_t jreg, scu_rev; -+ -+ /* -+ * If VGA isn't enabled, we need to enable now or subsequent -+ * access to the scratch registers will fail. We also inform -+ * our caller that it needs to POST the chip -+ * (Assumption: VGA not enabled -> need to POST) -+ */ -+ if (!ast_is_vga_enabled(dev)) { -+ ast_enable_vga(dev); -+ DRM_INFO("VGA not enabled on entry, requesting chip POST\n"); -+ *need_post = true; -+ } else -+ *need_post = false; -+ -+ -+ /* Enable extended register access */ -+ ast_enable_mmio(dev); - ast_open_key(ast); - -+ /* Find out whether P2A works or whether to use device-tree */ -+ ast_detect_config_mode(dev, &scu_rev); -+ -+ /* Identify chipset */ - if (dev->pdev->device == PCI_CHIP_AST1180) { - ast->chip = AST1100; - DRM_INFO("AST 1180 detected\n"); -@@ -80,12 +151,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - ast->chip = AST2300; - DRM_INFO("AST 2300 detected\n"); - } else if (dev->pdev->revision >= 0x10) { -- uint32_t data; -- ast_write32(ast, 0xf004, 0x1e6e0000); -- ast_write32(ast, 0xf000, 0x1); -- -- data = ast_read32(ast, 0x1207c); -- switch (data & 0x0300) { -+ switch (scu_rev & 0x0300) { - case 0x0200: - ast->chip = AST1100; - DRM_INFO("AST 1100 detected\n"); -@@ -110,26 +176,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - } - } - -- /* -- * If VGA isn't enabled, we need to enable now or subsequent -- * access to the scratch registers will fail. We also inform -- * our caller that it needs to POST the chip -- * (Assumption: VGA not enabled -> need to POST) -- */ -- if (!ast_is_vga_enabled(dev)) { -- ast_enable_vga(dev); -- ast_enable_mmio(dev); -- DRM_INFO("VGA not enabled on entry, requesting chip POST\n"); -- *need_post = true; -- } else -- *need_post = false; -- -- /* Check P2A Access */ -- ast->DisableP2A = true; -- data = ast_read32(ast, 0xf004); -- if (data != 0xFFFFFFFF) -- ast->DisableP2A = false; -- - /* Check if we support wide screen */ - switch (ast->chip) { - case AST1180: -@@ -146,17 +192,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - ast->support_wide_screen = true; - else { - ast->support_wide_screen = false; -- if (ast->DisableP2A == false) { -- /* Read SCU7c (silicon revision register) */ -- ast_write32(ast, 0xf004, 0x1e6e0000); -- ast_write32(ast, 0xf000, 0x1); -- data = ast_read32(ast, 0x1207c); -- data &= 0x300; -- if (ast->chip == AST2300 && data == 0x0) /* ast1300 */ -- ast->support_wide_screen = true; -- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */ -- ast->support_wide_screen = true; -- } -+ if (ast->chip == AST2300 && -+ (scu_rev & 0x300) == 0x0) /* ast1300 */ -+ ast->support_wide_screen = true; -+ if (ast->chip == AST2400 && -+ (scu_rev & 0x300) == 0x100) /* ast1400 */ -+ ast->support_wide_screen = true; - } - break; - } -@@ -220,85 +261,102 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) - - static int ast_get_dram_info(struct drm_device *dev) - { -+ struct device_node *np = dev->pdev->dev.of_node; - struct ast_private *ast = dev->dev_private; -- uint32_t data, data2; -- uint32_t denum, num, div, ref_pll; -+ uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; -+ uint32_t denum, num, div, ref_pll, dsel; - -- if (ast->DisableP2A) -- { -+ switch (ast->config_mode) { -+ case ast_use_dt: -+ /* -+ * If some properties are missing, use reasonable -+ * defaults for AST2400 -+ */ -+ if (of_property_read_u32(np, "aspeed,mcr-configuration", -+ &mcr_cfg)) -+ mcr_cfg = 0x00000577; -+ if (of_property_read_u32(np, "aspeed,mcr-scu-mpll", -+ &mcr_scu_mpll)) -+ mcr_scu_mpll = 0x000050C0; -+ if (of_property_read_u32(np, "aspeed,mcr-scu-strap", -+ &mcr_scu_strap)) -+ mcr_scu_strap = 0; -+ break; -+ case ast_use_p2a: -+ ast_write32(ast, 0xf004, 0x1e6e0000); -+ ast_write32(ast, 0xf000, 0x1); -+ mcr_cfg = ast_read32(ast, 0x10004); -+ mcr_scu_mpll = ast_read32(ast, 0x10120); -+ mcr_scu_strap = ast_read32(ast, 0x10170); -+ break; -+ case ast_use_defaults: -+ default: - ast->dram_bus_width = 16; - ast->dram_type = AST_DRAM_1Gx16; - ast->mclk = 396; -+ return 0; - } -- else -- { -- ast_write32(ast, 0xf004, 0x1e6e0000); -- ast_write32(ast, 0xf000, 0x1); -- data = ast_read32(ast, 0x10004); -- -- if (data & 0x40) -- ast->dram_bus_width = 16; -- else -- ast->dram_bus_width = 32; - -- if (ast->chip == AST2300 || ast->chip == AST2400) { -- switch (data & 0x03) { -- case 0: -- ast->dram_type = AST_DRAM_512Mx16; -- break; -- default: -- case 1: -- ast->dram_type = AST_DRAM_1Gx16; -- break; -- case 2: -- ast->dram_type = AST_DRAM_2Gx16; -- break; -- case 3: -- ast->dram_type = AST_DRAM_4Gx16; -- break; -- } -- } else { -- switch (data & 0x0c) { -- case 0: -- case 4: -- ast->dram_type = AST_DRAM_512Mx16; -- break; -- case 8: -- if (data & 0x40) -- ast->dram_type = AST_DRAM_1Gx16; -- else -- ast->dram_type = AST_DRAM_512Mx32; -- break; -- case 0xc: -- ast->dram_type = AST_DRAM_1Gx32; -- break; -- } -- } -+ if (mcr_cfg & 0x40) -+ ast->dram_bus_width = 16; -+ else -+ ast->dram_bus_width = 32; - -- data = ast_read32(ast, 0x10120); -- data2 = ast_read32(ast, 0x10170); -- if (data2 & 0x2000) -- ref_pll = 14318; -- else -- ref_pll = 12000; -- -- denum = data & 0x1f; -- num = (data & 0x3fe0) >> 5; -- data = (data & 0xc000) >> 14; -- switch (data) { -- case 3: -- div = 0x4; -+ if (ast->chip == AST2300 || ast->chip == AST2400) { -+ switch (mcr_cfg & 0x03) { -+ case 0: -+ ast->dram_type = AST_DRAM_512Mx16; - break; -- case 2: -+ default: - case 1: -- div = 0x2; -+ ast->dram_type = AST_DRAM_1Gx16; - break; -- default: -- div = 0x1; -+ case 2: -+ ast->dram_type = AST_DRAM_2Gx16; -+ break; -+ case 3: -+ ast->dram_type = AST_DRAM_4Gx16; -+ break; -+ } -+ } else { -+ switch (mcr_cfg & 0x0c) { -+ case 0: -+ case 4: -+ ast->dram_type = AST_DRAM_512Mx16; -+ break; -+ case 8: -+ if (mcr_cfg & 0x40) -+ ast->dram_type = AST_DRAM_1Gx16; -+ else -+ ast->dram_type = AST_DRAM_512Mx32; -+ break; -+ case 0xc: -+ ast->dram_type = AST_DRAM_1Gx32; - break; - } -- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); - } -+ -+ if (mcr_scu_strap & 0x2000) -+ ref_pll = 14318; -+ else -+ ref_pll = 12000; -+ -+ denum = mcr_scu_mpll & 0x1f; -+ num = (mcr_scu_mpll & 0x3fe0) >> 5; -+ dsel = (mcr_scu_mpll & 0xc000) >> 14; -+ switch (dsel) { -+ case 3: -+ div = 0x4; -+ break; -+ case 2: -+ case 1: -+ div = 0x2; -+ break; -+ default: -+ div = 0x1; -+ break; -+ } -+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); - return 0; - } - -diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c -index 270e8fb2803f..c7c58becb25d 100644 ---- a/drivers/gpu/drm/ast/ast_post.c -+++ b/drivers/gpu/drm/ast/ast_post.c -@@ -375,17 +375,14 @@ void ast_post_gpu(struct drm_device *dev) - ast_enable_mmio(dev); - ast_set_def_ext_reg(dev); - -- if (ast->DisableP2A == false) -- { -+ if (ast->config_mode == ast_use_p2a) { - if (ast->chip == AST2300 || ast->chip == AST2400) - ast_init_dram_2300(dev); - else - ast_init_dram_reg(dev); - - ast_init_3rdtx(dev); -- } -- else -- { -+ } else { - if (ast->tx_chip_type != AST_TX_NONE) - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ - } -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c -index 13db8a2851ed..1f013d45c9e9 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c -@@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man) - list_for_each_entry_safe(entry, next, &man->list, head) - vmw_cmdbuf_res_free(man, entry); - -+ drm_ht_remove(&man->resources); - kfree(man); - } - -diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c -index 0b80633bae91..d4d655a10df1 100644 ---- a/drivers/hid/i2c-hid/i2c-hid.c -+++ b/drivers/hid/i2c-hid/i2c-hid.c -@@ -364,6 +364,15 @@ static int i2c_hid_hwreset(struct i2c_client *client) - if (ret) - return ret; - -+ /* -+ * The HID over I2C specification states that if a DEVICE needs time -+ * after the PWR_ON request, it should utilise CLOCK stretching. -+ * However, it has been observered that the Windows driver provides a -+ * 1ms sleep between the PWR_ON and RESET requests and that some devices -+ * rely on this. -+ */ -+ usleep_range(1000, 5000); -+ - i2c_hid_dbg(ihid, "resetting...\n"); - - ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0); -diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c -index 4831eb910fc7..22160e481794 100644 ---- a/drivers/iommu/amd_iommu_v2.c -+++ b/drivers/iommu/amd_iommu_v2.c -@@ -699,9 +699,9 @@ out_clear_state: - - out_unregister: - mmu_notifier_unregister(&pasid_state->mn, mm); -+ mmput(mm); - - out_free: -- mmput(mm); - free_pasid_state(pasid_state); - - out: -diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c -index b92b8a724efb..f9711aceef54 100644 ---- a/drivers/iommu/intel-iommu.c -+++ b/drivers/iommu/intel-iommu.c -@@ -1137,7 +1137,7 @@ static void dma_pte_free_level(struct dmar_domain *domain, int level, - if (!dma_pte_present(pte) || dma_pte_superpage(pte)) - goto next; - -- level_pfn = pfn & level_mask(level - 1); -+ level_pfn = pfn & level_mask(level); - level_pte = phys_to_virt(dma_pte_addr(pte)); - - if (level > 2) -diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c -index 515bb8b80952..a070fa39521a 100644 ---- a/drivers/iommu/iommu.c -+++ b/drivers/iommu/iommu.c -@@ -391,36 +391,30 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev) - device->dev = dev; - - ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group"); -- if (ret) { -- kfree(device); -- return ret; -- } -+ if (ret) -+ goto err_free_device; - - device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj)); - rename: - if (!device->name) { -- sysfs_remove_link(&dev->kobj, "iommu_group"); -- kfree(device); -- return -ENOMEM; -+ ret = -ENOMEM; -+ goto err_remove_link; - } - - ret = sysfs_create_link_nowarn(group->devices_kobj, - &dev->kobj, device->name); - if (ret) { -- kfree(device->name); - if (ret == -EEXIST && i >= 0) { - /* - * Account for the slim chance of collision - * and append an instance to the name. - */ -+ kfree(device->name); - device->name = kasprintf(GFP_KERNEL, "%s.%d", - kobject_name(&dev->kobj), i++); - goto rename; - } -- -- sysfs_remove_link(&dev->kobj, "iommu_group"); -- kfree(device); -- return ret; -+ goto err_free_name; - } - - kobject_get(group->devices_kobj); -@@ -432,8 +426,10 @@ rename: - mutex_lock(&group->mutex); - list_add_tail(&device->list, &group->devices); - if (group->domain) -- __iommu_attach_device(group->domain, dev); -+ ret = __iommu_attach_device(group->domain, dev); - mutex_unlock(&group->mutex); -+ if (ret) -+ goto err_put_group; - - /* Notify any listeners about change to group. */ - blocking_notifier_call_chain(&group->notifier, -@@ -444,6 +440,21 @@ rename: - pr_info("Adding device %s to group %d\n", dev_name(dev), group->id); - - return 0; -+ -+err_put_group: -+ mutex_lock(&group->mutex); -+ list_del(&device->list); -+ mutex_unlock(&group->mutex); -+ dev->iommu_group = NULL; -+ kobject_put(group->devices_kobj); -+err_free_name: -+ kfree(device->name); -+err_remove_link: -+ sysfs_remove_link(&dev->kobj, "iommu_group"); -+err_free_device: -+ kfree(device); -+ pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret); -+ return ret; - } - EXPORT_SYMBOL_GPL(iommu_group_add_device); - -diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c -index 5abab8800891..9190057535e6 100644 ---- a/drivers/mtd/bcm47xxpart.c -+++ b/drivers/mtd/bcm47xxpart.c -@@ -66,11 +66,13 @@ static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, - { - uint32_t buf; - size_t bytes_read; -+ int err; - -- if (mtd_read(master, offset, sizeof(buf), &bytes_read, -- (uint8_t *)&buf) < 0) { -- pr_err("mtd_read error while parsing (offset: 0x%X)!\n", -- offset); -+ err = mtd_read(master, offset, sizeof(buf), &bytes_read, -+ (uint8_t *)&buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", -+ offset, err); - goto out_default; - } - -@@ -95,6 +97,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, - int trx_part = -1; - int last_trx_part = -1; - int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; -+ int err; - - /* - * Some really old flashes (like AT45DB*) had smaller erasesize-s, but -@@ -118,8 +121,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, - /* Parse block by block looking for magics */ - for (offset = 0; offset <= master->size - blocksize; - offset += blocksize) { -- /* Nothing more in higher memory */ -- if (offset >= 0x2000000) -+ /* Nothing more in higher memory on BCM47XX (MIPS) */ -+ if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000) - break; - - if (curr_part >= BCM47XXPART_MAX_PARTS) { -@@ -128,10 +131,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, - } - - /* Read beginning of the block */ -- if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, -- &bytes_read, (uint8_t *)buf) < 0) { -- pr_err("mtd_read error while parsing (offset: 0x%X)!\n", -- offset); -+ err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, -+ &bytes_read, (uint8_t *)buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", -+ offset, err); - continue; - } - -@@ -252,10 +256,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, - } - - /* Read middle of the block */ -- if (mtd_read(master, offset + 0x8000, 0x4, -- &bytes_read, (uint8_t *)buf) < 0) { -- pr_err("mtd_read error while parsing (offset: 0x%X)!\n", -- offset); -+ err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read, -+ (uint8_t *)buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", -+ offset, err); - continue; - } - -@@ -275,10 +280,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, - } - - offset = master->size - possible_nvram_sizes[i]; -- if (mtd_read(master, offset, 0x4, &bytes_read, -- (uint8_t *)buf) < 0) { -- pr_err("mtd_read error while reading at offset 0x%X!\n", -- offset); -+ err = mtd_read(master, offset, 0x4, &bytes_read, -+ (uint8_t *)buf); -+ if (err && !mtd_is_bitflip(err)) { -+ pr_err("mtd_read error while reading (offset 0x%X): %d\n", -+ offset, err); - continue; - } - -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -index 5e6238e0b2bd..75e6e7e6baed 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -@@ -2732,8 +2732,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata) - - /* Flush Tx queues */ - ret = xgbe_flush_tx_queues(pdata); -- if (ret) -+ if (ret) { -+ netdev_err(pdata->netdev, "error flushing TX queues\n"); - return ret; -+ } - - /* - * Initialize DMA related features -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -index 865b7e0b133b..64034ff081a0 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -@@ -877,7 +877,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata) - - DBGPR("-->xgbe_start\n"); - -- hw_if->init(pdata); -+ ret = hw_if->init(pdata); -+ if (ret) -+ return ret; - - ret = phy_if->phy_start(pdata); - if (ret) -diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c -index b56c9c581359..70da30095b89 100644 ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -255,15 +255,16 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring) - while (ring->start != ring->end) { - int slot_idx = ring->start % BGMAC_TX_RING_SLOTS; - struct bgmac_slot_info *slot = &ring->slots[slot_idx]; -- u32 ctl1; -+ u32 ctl0, ctl1; - int len; - - if (slot_idx == empty_slot) - break; - -+ ctl0 = le32_to_cpu(ring->cpu_base[slot_idx].ctl0); - ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1); - len = ctl1 & BGMAC_DESC_CTL1_LEN; -- if (ctl1 & BGMAC_DESC_CTL0_SOF) -+ if (ctl0 & BGMAC_DESC_CTL0_SOF) - /* Unmap no longer used buffer */ - dma_unmap_single(dma_dev, slot->dma_addr, len, - DMA_TO_DEVICE); -@@ -469,6 +470,11 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, - len -= ETH_FCS_LEN; - - skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); -+ if (unlikely(!skb)) { -+ bgmac_err(bgmac, "build_skb failed\n"); -+ put_page(virt_to_head_page(buf)); -+ break; -+ } - skb_put(skb, BGMAC_RX_FRAME_OFFSET + - BGMAC_RX_BUF_OFFSET + len); - skb_pull(skb, BGMAC_RX_FRAME_OFFSET + -@@ -1302,7 +1308,8 @@ static int bgmac_open(struct net_device *net_dev) - - phy_start(bgmac->phy_dev); - -- netif_carrier_on(net_dev); -+ netif_start_queue(net_dev); -+ - return 0; - } - -diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c -index 1795c935ff02..7b8638ddb673 100644 ---- a/drivers/net/ethernet/emulex/benet/be_cmds.c -+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c -@@ -1052,7 +1052,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, - err: - spin_unlock_bh(&adapter->mcc_lock); - -- if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) -+ if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST) - status = -EPERM; - - return status; -diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c -index 6a061f17a44f..4cd2a7d0124f 100644 ---- a/drivers/net/ethernet/freescale/gianfar.c -+++ b/drivers/net/ethernet/freescale/gianfar.c -@@ -2939,7 +2939,7 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus, - size, GFAR_RXB_TRUESIZE); - - /* try reuse page */ -- if (unlikely(page_count(page) != 1)) -+ if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page))) - return false; - - /* change offset to the other half */ -diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c -index f9e4988ea30e..2f9b12cf9ee5 100644 ---- a/drivers/net/ethernet/ibm/ibmveth.c -+++ b/drivers/net/ethernet/ibm/ibmveth.c -@@ -1602,8 +1602,11 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) - netdev->netdev_ops = &ibmveth_netdev_ops; - netdev->ethtool_ops = &netdev_ethtool_ops; - SET_NETDEV_DEV(netdev, &dev->dev); -- netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | -- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -+ netdev->hw_features = NETIF_F_SG; -+ if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) { -+ netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -+ NETIF_F_RXCSUM; -+ } - - netdev->features |= netdev->hw_features; - -diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c -index d74f5f4e5782..07eabf72c480 100644 ---- a/drivers/net/ethernet/korina.c -+++ b/drivers/net/ethernet/korina.c -@@ -900,10 +900,10 @@ static void korina_restart_task(struct work_struct *work) - DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR, - &lp->rx_dma_regs->dmasm); - -- korina_free_ring(dev); -- - napi_disable(&lp->napi); - -+ korina_free_ring(dev); -+ - if (korina_init(dev) < 0) { - printk(KERN_ERR "%s: cannot restart device\n", dev->name); - return; -@@ -1064,12 +1064,12 @@ static int korina_close(struct net_device *dev) - tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR; - writel(tmp, &lp->rx_dma_regs->dmasm); - -- korina_free_ring(dev); -- - napi_disable(&lp->napi); - - cancel_work_sync(&lp->restart_task); - -+ korina_free_ring(dev); -+ - free_irq(lp->rx_irq, dev); - free_irq(lp->tx_irq, dev); - free_irq(lp->ovr_irq, dev); -diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c -index 603d1c3d3b2e..ff77b8b608bd 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/eq.c -+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c -@@ -542,8 +542,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) - break; - - case MLX4_EVENT_TYPE_SRQ_LIMIT: -- mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n", -- __func__); -+ mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n", -+ __func__, be32_to_cpu(eqe->event.srq.srqn), -+ eq->eqn); - case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - if (mlx4_is_master(dev)) { - /* forward only to slave owning the SRQ */ -@@ -558,15 +559,19 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) - eq->eqn, eq->cons_index, ret); - break; - } -- mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", -- __func__, slave, -- be32_to_cpu(eqe->event.srq.srqn), -- eqe->type, eqe->subtype); -+ if (eqe->type == -+ MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) -+ mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", -+ __func__, slave, -+ be32_to_cpu(eqe->event.srq.srqn), -+ eqe->type, eqe->subtype); - - if (!ret && slave != dev->caps.function) { -- mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", -- __func__, eqe->type, -- eqe->subtype, slave); -+ if (eqe->type == -+ MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) -+ mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", -+ __func__, eqe->type, -+ eqe->subtype, slave); - mlx4_slave_event(dev, slave, eqe); - break; - } -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c -index 1e611980cf99..f5c1f4acc57b 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/main.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c -@@ -153,8 +153,9 @@ static struct mlx5_profile profile[] = { - }, - }; - --#define FW_INIT_TIMEOUT_MILI 2000 --#define FW_INIT_WAIT_MS 2 -+#define FW_INIT_TIMEOUT_MILI 2000 -+#define FW_INIT_WAIT_MS 2 -+#define FW_PRE_INIT_TIMEOUT_MILI 10000 - - static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili) - { -@@ -934,6 +935,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) - */ - dev->state = MLX5_DEVICE_STATE_UP; - -+ /* wait for firmware to accept initialization segments configurations -+ */ -+ err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI); -+ if (err) { -+ dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", -+ FW_PRE_INIT_TIMEOUT_MILI); -+ goto out; -+ } -+ - err = mlx5_cmd_init(dev); - if (err) { - dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); -diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c -index 1e61d4da72db..585e90f8341d 100644 ---- a/drivers/net/ethernet/renesas/ravb_main.c -+++ b/drivers/net/ethernet/renesas/ravb_main.c -@@ -221,18 +221,6 @@ static void ravb_ring_free(struct net_device *ndev, int q) - int ring_size; - int i; - -- /* Free RX skb ringbuffer */ -- if (priv->rx_skb[q]) { -- for (i = 0; i < priv->num_rx_ring[q]; i++) -- dev_kfree_skb(priv->rx_skb[q][i]); -- } -- kfree(priv->rx_skb[q]); -- priv->rx_skb[q] = NULL; -- -- /* Free aligned TX buffers */ -- kfree(priv->tx_align[q]); -- priv->tx_align[q] = NULL; -- - if (priv->rx_ring[q]) { - for (i = 0; i < priv->num_rx_ring[q]; i++) { - struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; -@@ -261,6 +249,18 @@ static void ravb_ring_free(struct net_device *ndev, int q) - priv->tx_ring[q] = NULL; - } - -+ /* Free RX skb ringbuffer */ -+ if (priv->rx_skb[q]) { -+ for (i = 0; i < priv->num_rx_ring[q]; i++) -+ dev_kfree_skb(priv->rx_skb[q][i]); -+ } -+ kfree(priv->rx_skb[q]); -+ priv->rx_skb[q] = NULL; -+ -+ /* Free aligned TX buffers */ -+ kfree(priv->tx_align[q]); -+ priv->tx_align[q] = NULL; -+ - /* Free TX skb ringbuffer. - * SKBs are freed by ravb_tx_free() call above. - */ -diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c -index d790cb8d9db3..8e832ba8ab24 100644 ---- a/drivers/net/ethernet/sfc/falcon.c -+++ b/drivers/net/ethernet/sfc/falcon.c -@@ -2796,6 +2796,11 @@ const struct efx_nic_type falcon_a1_nic_type = { - .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .offload_features = NETIF_F_IP_CSUM, - .mcdi_max_ver = -1, -+#ifdef CONFIG_SFC_SRIOV -+ .vswitching_probe = efx_port_dummy_op_int, -+ .vswitching_restore = efx_port_dummy_op_int, -+ .vswitching_remove = efx_port_dummy_op_void, -+#endif - }; - - const struct efx_nic_type falcon_b0_nic_type = { -@@ -2897,4 +2902,9 @@ const struct efx_nic_type falcon_b0_nic_type = { - .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, - .mcdi_max_ver = -1, - .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, -+#ifdef CONFIG_SFC_SRIOV -+ .vswitching_probe = efx_port_dummy_op_int, -+ .vswitching_restore = efx_port_dummy_op_int, -+ .vswitching_remove = efx_port_dummy_op_void, -+#endif - }; -diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c -index 7f7c87762bc6..8dfc75250583 100644 ---- a/drivers/net/virtio_net.c -+++ b/drivers/net/virtio_net.c -@@ -47,8 +47,16 @@ module_param(gso, bool, 0444); - */ - DECLARE_EWMA(pkt_len, 1, 64) - -+/* With mergeable buffers we align buffer address and use the low bits to -+ * encode its true size. Buffer size is up to 1 page so we need to align to -+ * square root of page size to ensure we reserve enough bits to encode the true -+ * size. -+ */ -+#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2) -+ - /* Minimum alignment for mergeable packet buffers. */ --#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256) -+#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \ -+ 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT) - - #define VIRTNET_DRIVER_VERSION "1.0.0" - -diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c -index 9a986ccd42e5..dab3bf6649e6 100644 ---- a/drivers/net/vxlan.c -+++ b/drivers/net/vxlan.c -@@ -2240,7 +2240,7 @@ static void vxlan_cleanup(unsigned long arg) - = container_of(p, struct vxlan_fdb, hlist); - unsigned long timeout; - -- if (f->state & NUD_PERMANENT) -+ if (f->state & (NUD_PERMANENT | NUD_NOARP)) - continue; - - timeout = f->used + vxlan->cfg.age_interval * HZ; -diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c -index 888e9cfef51a..34a062ccb11d 100644 ---- a/drivers/net/xen-netfront.c -+++ b/drivers/net/xen-netfront.c -@@ -321,7 +321,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) - queue->rx.req_prod_pvt = req_prod; - - /* Not enough requests? Try again later. */ -- if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) { -+ if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) { - mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10)); - return; - } -diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c -index be3bc2f4edd4..09cc64b3b695 100644 ---- a/drivers/platform/x86/ideapad-laptop.c -+++ b/drivers/platform/x86/ideapad-laptop.c -@@ -807,6 +807,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) - case 11: - case 7: - case 6: -+ case 1: - ideapad_input_report(priv, vpc_bit); - break; - case 5: -diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c -index 59ced8864b2f..0e6aaef9a038 100644 ---- a/drivers/scsi/lpfc/lpfc_els.c -+++ b/drivers/scsi/lpfc/lpfc_els.c -@@ -3563,12 +3563,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) - } else { - buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; - lpfc_els_free_data(phba, buf_ptr1); -+ elsiocb->context2 = NULL; - } - } - - if (elsiocb->context3) { - buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3; - lpfc_els_free_bpl(phba, buf_ptr); -+ elsiocb->context3 = NULL; - } - lpfc_sli_release_iocbq(phba, elsiocb); - return 0; -diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c -index f5aeda8f014f..38e90d9c2ced 100644 ---- a/drivers/scsi/lpfc/lpfc_sli.c -+++ b/drivers/scsi/lpfc/lpfc_sli.c -@@ -5887,18 +5887,25 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) - - free_vfi_bmask: - kfree(phba->sli4_hba.vfi_bmask); -+ phba->sli4_hba.vfi_bmask = NULL; - free_xri_ids: - kfree(phba->sli4_hba.xri_ids); -+ phba->sli4_hba.xri_ids = NULL; - free_xri_bmask: - kfree(phba->sli4_hba.xri_bmask); -+ phba->sli4_hba.xri_bmask = NULL; - free_vpi_ids: - kfree(phba->vpi_ids); -+ phba->vpi_ids = NULL; - free_vpi_bmask: - kfree(phba->vpi_bmask); -+ phba->vpi_bmask = NULL; - free_rpi_ids: - kfree(phba->sli4_hba.rpi_ids); -+ phba->sli4_hba.rpi_ids = NULL; - free_rpi_bmask: - kfree(phba->sli4_hba.rpi_bmask); -+ phba->sli4_hba.rpi_bmask = NULL; - err_exit: - return rc; - } -diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c -index 0e59731f95ad..1f6a3b86965f 100644 ---- a/drivers/scsi/qla2xxx/qla_isr.c -+++ b/drivers/scsi/qla2xxx/qla_isr.c -@@ -2466,6 +2466,10 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) - if (pkt->entry_status & RF_BUSY) - res = DID_BUS_BUSY << 16; - -+ if (pkt->entry_type == NOTIFY_ACK_TYPE && -+ pkt->handle == QLA_TGT_SKIP_HANDLE) -+ return; -+ - sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); - if (sp) { - sp->done(ha, sp, res); -diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c -index f57d96984ae4..e6faa0b050d1 100644 ---- a/drivers/scsi/qla2xxx/qla_target.c -+++ b/drivers/scsi/qla2xxx/qla_target.c -@@ -2865,7 +2865,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, - - pkt->entry_type = NOTIFY_ACK_TYPE; - pkt->entry_count = 1; -- pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; -+ pkt->handle = QLA_TGT_SKIP_HANDLE; - - nack = (struct nack_to_isp *)pkt; - nack->ox_id = ntfy->ox_id; -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index 4d5207dff960..8750c86f95f9 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -2566,7 +2566,8 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) - if (sdp->broken_fua) { - sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n"); - sdkp->DPOFUA = 0; -- } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { -+ } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw && -+ !sdkp->device->use_16_for_rw) { - sd_first_printk(KERN_NOTICE, sdkp, - "Uses READ/WRITE(6), disabling FUA\n"); - sdkp->DPOFUA = 0; -diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c -index 7dbbb29d24c6..03a2aadf0d3c 100644 ---- a/drivers/scsi/virtio_scsi.c -+++ b/drivers/scsi/virtio_scsi.c -@@ -533,7 +533,9 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, - { - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); -+ unsigned long flags; - int req_size; -+ int ret; - - BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); - -@@ -561,8 +563,15 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, - req_size = sizeof(cmd->req.cmd); - } - -- if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0) -+ ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)); -+ if (ret == -EIO) { -+ cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; -+ spin_lock_irqsave(&req_vq->vq_lock, flags); -+ virtscsi_complete_cmd(vscsi, cmd); -+ spin_unlock_irqrestore(&req_vq->vq_lock, flags); -+ } else if (ret != 0) { - return SCSI_MLQUEUE_HOST_BUSY; -+ } - return 0; - } - -diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c -index 7d3af3eacf57..1ddba9ae8c0f 100644 ---- a/drivers/spi/spi-davinci.c -+++ b/drivers/spi/spi-davinci.c -@@ -651,7 +651,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) - buf = t->rx_buf; - t->rx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_FROM_DEVICE); -- if (!t->rx_dma) { -+ if (dma_mapping_error(&spi->dev, !t->rx_dma)) { - ret = -EFAULT; - goto err_rx_map; - } -@@ -665,7 +665,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) - buf = (void *)t->tx_buf; - t->tx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_TO_DEVICE); -- if (!t->tx_dma) { -+ if (dma_mapping_error(&spi->dev, t->tx_dma)) { - ret = -EFAULT; - goto err_tx_map; - } -diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c -index 6d8f865a2fb7..732e6ed5d7b4 100644 ---- a/drivers/usb/gadget/function/f_fs.c -+++ b/drivers/usb/gadget/function/f_fs.c -@@ -3463,6 +3463,7 @@ static void ffs_closed(struct ffs_data *ffs) - { - struct ffs_dev *ffs_obj; - struct f_fs_opts *opts; -+ struct config_item *ci; - - ENTER(); - ffs_dev_lock(); -@@ -3486,8 +3487,11 @@ static void ffs_closed(struct ffs_data *ffs) - || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount)) - goto done; - -- unregister_gadget_item(ffs_obj->opts-> -- func_inst.group.cg_item.ci_parent->ci_parent); -+ ci = opts->func_inst.group.cg_item.ci_parent->ci_parent; -+ ffs_dev_unlock(); -+ -+ unregister_gadget_item(ci); -+ return; - done: - ffs_dev_unlock(); - } -diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c -index 1a9f18b40be6..34e4b3ad8b92 100644 ---- a/drivers/vfio/vfio_iommu_spapr_tce.c -+++ b/drivers/vfio/vfio_iommu_spapr_tce.c -@@ -1163,6 +1163,10 @@ static int tce_iommu_attach_group(void *iommu_data, - /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n", - iommu_group_id(iommu_group), iommu_group); */ - table_group = iommu_group_get_iommudata(iommu_group); -+ if (!table_group) { -+ ret = -ENODEV; -+ goto unlock_exit; -+ } - - if (tce_groups_attached(container) && (!table_group->ops || - !table_group->ops->take_ownership || -diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c -index e0c98423f2c9..11a72bc2c71b 100644 ---- a/drivers/watchdog/bcm_kona_wdt.c -+++ b/drivers/watchdog/bcm_kona_wdt.c -@@ -304,6 +304,8 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) - if (!wdt) - return -ENOMEM; - -+ spin_lock_init(&wdt->lock); -+ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - wdt->base = devm_ioremap_resource(dev, res); - if (IS_ERR(wdt->base)) -@@ -316,7 +318,6 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) - return ret; - } - -- spin_lock_init(&wdt->lock); - platform_set_drvdata(pdev, wdt); - watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); - bcm_kona_wdt_wdd.parent = &pdev->dev; -diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c -index 7399782c0998..8a58bbc14de2 100644 ---- a/drivers/xen/swiotlb-xen.c -+++ b/drivers/xen/swiotlb-xen.c -@@ -409,9 +409,9 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, - if (map == SWIOTLB_MAP_ERROR) - return DMA_ERROR_CODE; - -+ dev_addr = xen_phys_to_bus(map); - xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT), - dev_addr, map & ~PAGE_MASK, size, dir, attrs); -- dev_addr = xen_phys_to_bus(map); - - /* - * Ensure that the address returned is DMA'ble -@@ -567,13 +567,14 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, - sg_dma_len(sgl) = 0; - return 0; - } -+ dev_addr = xen_phys_to_bus(map); - xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT), - dev_addr, - map & ~PAGE_MASK, - sg->length, - dir, - attrs); -- sg->dma_address = xen_phys_to_bus(map); -+ sg->dma_address = dev_addr; - } else { - /* we are not interested in the dma_addr returned by - * xen_dma_map_page, only in the potential cache flushes executed -diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 3a93755e880f..29ef427c0652 100644 ---- a/fs/binfmt_elf.c -+++ b/fs/binfmt_elf.c -@@ -2295,6 +2295,7 @@ static int elf_core_dump(struct coredump_params *cprm) - goto end_coredump; - } - } -+ dump_truncate(cprm); - - if (!elf_core_write_extra_data(cprm)) - goto end_coredump; -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 863fa0f1972b..a61926cb01c0 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -4397,8 +4397,19 @@ search_again: - if (found_type > min_type) { - del_item = 1; - } else { -- if (item_end < new_size) -+ if (item_end < new_size) { -+ /* -+ * With NO_HOLES mode, for the following mapping -+ * -+ * [0-4k][hole][8k-12k] -+ * -+ * if truncating isize down to 6k, it ends up -+ * isize being 8k. -+ */ -+ if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) -+ last_size = new_size; - break; -+ } - if (found_key.offset >= new_size) - del_item = 1; - else -diff --git a/fs/coredump.c b/fs/coredump.c -index 5d15c4975ba1..a8852293038a 100644 ---- a/fs/coredump.c -+++ b/fs/coredump.c -@@ -810,3 +810,21 @@ int dump_align(struct coredump_params *cprm, int align) - return mod ? dump_skip(cprm, align - mod) : 1; - } - EXPORT_SYMBOL(dump_align); -+ -+/* -+ * Ensures that file size is big enough to contain the current file -+ * postion. This prevents gdb from complaining about a truncated file -+ * if the last "write" to the file was dump_skip. -+ */ -+void dump_truncate(struct coredump_params *cprm) -+{ -+ struct file *file = cprm->file; -+ loff_t offset; -+ -+ if (file->f_op->llseek && file->f_op->llseek != no_llseek) { -+ offset = file->f_op->llseek(file, 0, SEEK_CUR); -+ if (i_size_read(file->f_mapping->host) < offset) -+ do_truncate(file->f_path.dentry, offset, 0, file); -+ } -+} -+EXPORT_SYMBOL(dump_truncate); -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 4e3679b25b9b..8e425f2c5ddd 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -2188,8 +2188,6 @@ static int nfs4_opendata_access(struct rpc_cred *cred, - if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0) - return 0; - -- /* even though OPEN succeeded, access is denied. Close the file */ -- nfs4_close_state(state, fmode); - return -EACCES; - } - -diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c -index 709fbbd44c65..acebc350e98d 100644 ---- a/fs/ocfs2/cluster/heartbeat.c -+++ b/fs/ocfs2/cluster/heartbeat.c -@@ -2070,13 +2070,13 @@ unlock: - spin_unlock(&o2hb_live_lock); - } - --static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item, -+static ssize_t o2hb_heartbeat_group_dead_threshold_show(struct config_item *item, - char *page) - { - return sprintf(page, "%u\n", o2hb_dead_threshold); - } - --static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item, -+static ssize_t o2hb_heartbeat_group_dead_threshold_store(struct config_item *item, - const char *page, size_t count) - { - unsigned long tmp; -@@ -2125,11 +2125,11 @@ static ssize_t o2hb_heartbeat_group_mode_store(struct config_item *item, - - } - --CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold); -+CONFIGFS_ATTR(o2hb_heartbeat_group_, dead_threshold); - CONFIGFS_ATTR(o2hb_heartbeat_group_, mode); - - static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = { -- &o2hb_heartbeat_group_attr_threshold, -+ &o2hb_heartbeat_group_attr_dead_threshold, - &o2hb_heartbeat_group_attr_mode, - NULL, - }; -diff --git a/include/linux/coredump.h b/include/linux/coredump.h -index d016a121a8c4..28ffa94aed6b 100644 ---- a/include/linux/coredump.h -+++ b/include/linux/coredump.h -@@ -14,6 +14,7 @@ struct coredump_params; - extern int dump_skip(struct coredump_params *cprm, size_t nr); - extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); - extern int dump_align(struct coredump_params *cprm, int align); -+extern void dump_truncate(struct coredump_params *cprm); - #ifdef CONFIG_COREDUMP - extern void do_coredump(const siginfo_t *siginfo); - #else -diff --git a/include/net/xfrm.h b/include/net/xfrm.h -index d6f6e5006ee9..185fb037b332 100644 ---- a/include/net/xfrm.h -+++ b/include/net/xfrm.h -@@ -948,10 +948,6 @@ struct xfrm_dst { - struct flow_cache_object flo; - struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; - int num_pols, num_xfrms; --#ifdef CONFIG_XFRM_SUB_POLICY -- struct flowi *origin; -- struct xfrm_selector *partner; --#endif - u32 xfrm_genid; - u32 policy_genid; - u32 route_mtu_cached; -@@ -967,12 +963,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) - dst_release(xdst->route); - if (likely(xdst->u.dst.xfrm)) - xfrm_state_put(xdst->u.dst.xfrm); --#ifdef CONFIG_XFRM_SUB_POLICY -- kfree(xdst->origin); -- xdst->origin = NULL; -- kfree(xdst->partner); -- xdst->partner = NULL; --#endif - } - #endif - -diff --git a/kernel/panic.c b/kernel/panic.c -index 41e2b54f36b5..1d07cf9af849 100644 ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -167,7 +167,7 @@ void panic(const char *fmt, ...) - * Delay timeout seconds before rebooting the machine. - * We can't use the "normal" timers since we just panicked. - */ -- pr_emerg("Rebooting in %d seconds..", panic_timeout); -+ pr_emerg("Rebooting in %d seconds..\n", panic_timeout); - - for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) { - touch_nmi_watchdog(); -diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c -index b0b93fd33af9..f8e8d68ed3fd 100644 ---- a/kernel/sched/loadavg.c -+++ b/kernel/sched/loadavg.c -@@ -201,8 +201,9 @@ void calc_load_exit_idle(void) - struct rq *this_rq = this_rq(); - - /* -- * If we're still before the sample window, we're done. -+ * If we're still before the pending sample window, we're done. - */ -+ this_rq->calc_load_update = calc_load_update; - if (time_before(jiffies, this_rq->calc_load_update)) - return; - -@@ -211,7 +212,6 @@ void calc_load_exit_idle(void) - * accounted through the nohz accounting, so skip the entire deal and - * sync up for the next window. - */ -- this_rq->calc_load_update = calc_load_update; - if (time_before(jiffies, this_rq->calc_load_update + 10)) - this_rq->calc_load_update += LOAD_FREQ; - } -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 300d64162aff..464a7864e4c5 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -174,7 +174,7 @@ extern int no_unaligned_warning; - #define SYSCTL_WRITES_WARN 0 - #define SYSCTL_WRITES_STRICT 1 - --static int sysctl_writes_strict = SYSCTL_WRITES_WARN; -+static int sysctl_writes_strict = SYSCTL_WRITES_STRICT; - - static int proc_do_cad_pid(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos); -diff --git a/lib/swiotlb.c b/lib/swiotlb.c -index 76f29ecba8f4..771234d050c7 100644 ---- a/lib/swiotlb.c -+++ b/lib/swiotlb.c -@@ -452,11 +452,11 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, - : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT); - - /* -- * For mappings greater than a page, we limit the stride (and -- * hence alignment) to a page size. -+ * For mappings greater than or equal to a page, we limit the stride -+ * (and hence alignment) to a page size. - */ - nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; -- if (size > PAGE_SIZE) -+ if (size >= PAGE_SIZE) - stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT)); - else - stride = 1; -diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 47b469663822..6c6f5ccfcda1 100644 ---- a/mm/huge_memory.c -+++ b/mm/huge_memory.c -@@ -1363,8 +1363,11 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, - */ - if (unlikely(pmd_trans_migrating(*pmdp))) { - page = pmd_page(*pmdp); -+ if (!get_page_unless_zero(page)) -+ goto out_unlock; - spin_unlock(ptl); - wait_on_page_locked(page); -+ put_page(page); - goto out; - } - -@@ -1396,8 +1399,11 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, - - /* Migration could have started since the pmd_trans_migrating check */ - if (!page_locked) { -+ if (!get_page_unless_zero(page)) -+ goto out_unlock; - spin_unlock(ptl); - wait_on_page_locked(page); -+ put_page(page); - page_nid = -1; - goto out; - } -diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c -index 40dd0f9b00d6..09f733b0424a 100644 ---- a/mm/swap_cgroup.c -+++ b/mm/swap_cgroup.c -@@ -205,6 +205,8 @@ void swap_cgroup_swapoff(int type) - struct page *page = map[i]; - if (page) - __free_page(page); -+ if (!(i % SWAP_CLUSTER_MAX)) -+ cond_resched(); - } - vfree(map); - } -diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c -index ad8d6e6b87ca..e20ae2d3c498 100644 ---- a/net/8021q/vlan.c -+++ b/net/8021q/vlan.c -@@ -278,7 +278,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) - return 0; - - out_free_newdev: -- free_netdev(new_dev); -+ if (new_dev->reg_state == NETREG_UNINITIALIZED) -+ free_netdev(new_dev); - return err; - } - -diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c -index 59ce1fcc220c..71b6ab240dea 100644 ---- a/net/caif/cfpkt_skbuff.c -+++ b/net/caif/cfpkt_skbuff.c -@@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) - { - struct sk_buff *skb; - -- if (likely(in_interrupt())) -- skb = alloc_skb(len + pfx, GFP_ATOMIC); -- else -- skb = alloc_skb(len + pfx, GFP_KERNEL); -- -+ skb = alloc_skb(len + pfx, GFP_ATOMIC); - if (unlikely(skb == NULL)) - return NULL; - -diff --git a/net/core/dev.c b/net/core/dev.c -index 87b8754f34ac..524d8b28e690 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1246,8 +1246,9 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) - if (!new_ifalias) - return -ENOMEM; - dev->ifalias = new_ifalias; -+ memcpy(dev->ifalias, alias, len); -+ dev->ifalias[len] = 0; - -- strlcpy(dev->ifalias, alias, len+1); - return len; - } - -diff --git a/net/core/dst.c b/net/core/dst.c -index d7ad628bf64e..e72d706f8d0c 100644 ---- a/net/core/dst.c -+++ b/net/core/dst.c -@@ -462,6 +462,20 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, - spin_lock_bh(&dst_garbage.lock); - dst = dst_garbage.list; - dst_garbage.list = NULL; -+ /* The code in dst_ifdown places a hold on the loopback device. -+ * If the gc entry processing is set to expire after a lengthy -+ * interval, this hold can cause netdev_wait_allrefs() to hang -+ * out and wait for a long time -- until the the loopback -+ * interface is released. If we're really unlucky, it'll emit -+ * pr_emerg messages to console too. Reset the interval here, -+ * so dst cleanups occur in a more timely fashion. -+ */ -+ if (dst_garbage.timer_inc > DST_GC_INC) { -+ dst_garbage.timer_inc = DST_GC_INC; -+ dst_garbage.timer_expires = DST_GC_MIN; -+ mod_delayed_work(system_wq, &dst_gc_work, -+ dst_garbage.timer_expires); -+ } - spin_unlock_bh(&dst_garbage.lock); - - if (last) -diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index d43544ce7550..2ec5324a7ff7 100644 ---- a/net/core/rtnetlink.c -+++ b/net/core/rtnetlink.c -@@ -897,6 +897,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, - + nla_total_size(1) /* IFLA_LINKMODE */ - + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ - + nla_total_size(4) /* IFLA_LINK_NETNSID */ -+ + nla_total_size(4) /* IFLA_GROUP */ - + nla_total_size(ext_filter_mask - & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ - + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ -@@ -1089,6 +1090,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, - struct ifla_vf_mac vf_mac; - struct ifla_vf_info ivi; - -+ memset(&ivi, 0, sizeof(ivi)); -+ - /* Not all SR-IOV capable drivers support the - * spoofcheck and "RSS query enable" query. Preset to - * -1 so the user space tool can detect that the driver -@@ -1097,7 +1100,6 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, - ivi.spoofchk = -1; - ivi.rss_query_en = -1; - ivi.trusted = -1; -- memset(ivi.mac, 0, sizeof(ivi.mac)); - /* The default value for VF link state is "auto" - * IFLA_VF_LINK_STATE_AUTO which equals zero - */ -@@ -1370,6 +1372,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { - [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, - [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, - [IFLA_PROTO_DOWN] = { .type = NLA_U8 }, -+ [IFLA_GROUP] = { .type = NLA_U32 }, - }; - - static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { -diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c -index b1dc096d22f8..403593bd2b83 100644 ---- a/net/decnet/dn_route.c -+++ b/net/decnet/dn_route.c -@@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_route *rt) - call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); - } - --static inline void dnrt_drop(struct dn_route *rt) --{ -- dst_release(&rt->dst); -- call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); --} -- - static void dn_dst_check_expire(unsigned long dummy) - { - int i; -@@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops) - } - *rtp = rt->dst.dn_next; - rt->dst.dn_next = NULL; -- dnrt_drop(rt); -+ dnrt_free(rt); - break; - } - spin_unlock_bh(&dn_rt_hash_table[i].lock); -@@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou - dst_use(&rth->dst, now); - spin_unlock_bh(&dn_rt_hash_table[hash].lock); - -- dnrt_drop(rt); -+ dst_free(&rt->dst); - *rp = rth; - return 0; - } -@@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long dummy) - for(; rt; rt = next) { - next = rcu_dereference_raw(rt->dst.dn_next); - RCU_INIT_POINTER(rt->dst.dn_next, NULL); -- dst_free((struct dst_entry *)rt); -+ dnrt_free(rt); - } - - nothing_to_declare: -@@ -1187,7 +1181,7 @@ make_route: - if (dev_out->flags & IFF_LOOPBACK) - flags |= RTCF_LOCAL; - -- rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST); -+ rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST); - if (rt == NULL) - goto e_nobufs; - -diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c -index 85f2fdc360c2..29246bc9a7b4 100644 ---- a/net/decnet/netfilter/dn_rtmsg.c -+++ b/net/decnet/netfilter/dn_rtmsg.c -@@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) - { - struct nlmsghdr *nlh = nlmsg_hdr(skb); - -- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) -+ if (skb->len < sizeof(*nlh) || -+ nlh->nlmsg_len < sizeof(*nlh) || -+ skb->len < nlh->nlmsg_len) - return; - - if (!netlink_capable(skb, CAP_NET_ADMIN)) -diff --git a/net/dsa/slave.c b/net/dsa/slave.c -index 8dfe9fb7ad36..554c2a961ad5 100644 ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -1006,10 +1006,8 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p, - /* Use already configured phy mode */ - if (p->phy_interface == PHY_INTERFACE_MODE_NA) - p->phy_interface = p->phy->interface; -- phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, -- p->phy_interface); -- -- return 0; -+ return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, -+ p->phy_interface); - } - - static int dsa_slave_phy_setup(struct dsa_slave_priv *p, -diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c -index 17adfdaf5795..3809d523d012 100644 ---- a/net/ipv4/igmp.c -+++ b/net/ipv4/igmp.c -@@ -1102,6 +1102,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) - pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); - if (!pmc) - return; -+ spin_lock_init(&pmc->lock); - spin_lock_bh(&im->lock); - pmc->interface = im->interface; - in_dev_hold(in_dev); -@@ -2026,21 +2027,26 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, - - static void ip_mc_clear_src(struct ip_mc_list *pmc) - { -- struct ip_sf_list *psf, *nextpsf; -+ struct ip_sf_list *psf, *nextpsf, *tomb, *sources; - -- for (psf = pmc->tomb; psf; psf = nextpsf) { -+ spin_lock_bh(&pmc->lock); -+ tomb = pmc->tomb; -+ pmc->tomb = NULL; -+ sources = pmc->sources; -+ pmc->sources = NULL; -+ pmc->sfmode = MCAST_EXCLUDE; -+ pmc->sfcount[MCAST_INCLUDE] = 0; -+ pmc->sfcount[MCAST_EXCLUDE] = 1; -+ spin_unlock_bh(&pmc->lock); -+ -+ for (psf = tomb; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } -- pmc->tomb = NULL; -- for (psf = pmc->sources; psf; psf = nextpsf) { -+ for (psf = sources; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } -- pmc->sources = NULL; -- pmc->sfmode = MCAST_EXCLUDE; -- pmc->sfcount[MCAST_INCLUDE] = 0; -- pmc->sfcount[MCAST_EXCLUDE] = 1; - } - - /* Join a multicast group -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 8cf3fc7c2932..03dadbf6cc5e 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -291,9 +291,9 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev, - static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, - unsigned long delay) - { -- if (!delayed_work_pending(&ifp->dad_work)) -- in6_ifa_hold(ifp); -- mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); -+ in6_ifa_hold(ifp); -+ if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay)) -+ in6_ifa_put(ifp); - } - - static int snmp6_alloc_dev(struct inet6_dev *idev) -diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c -index ed33abf57abd..9ac4f0cef27d 100644 ---- a/net/ipv6/fib6_rules.c -+++ b/net/ipv6/fib6_rules.c -@@ -32,7 +32,6 @@ struct fib6_rule { - struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, - int flags, pol_lookup_t lookup) - { -- struct rt6_info *rt; - struct fib_lookup_arg arg = { - .lookup_ptr = lookup, - .flags = FIB_LOOKUP_NOREF, -@@ -41,21 +40,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, - fib_rules_lookup(net->ipv6.fib6_rules_ops, - flowi6_to_flowi(fl6), flags, &arg); - -- rt = arg.result; -+ if (arg.result) -+ return arg.result; - -- if (!rt) { -- dst_hold(&net->ipv6.ip6_null_entry->dst); -- return &net->ipv6.ip6_null_entry->dst; -- } -- -- if (rt->rt6i_flags & RTF_REJECT && -- rt->dst.error == -EAGAIN) { -- ip6_rt_put(rt); -- rt = net->ipv6.ip6_null_entry; -- dst_hold(&rt->dst); -- } -- -- return &rt->dst; -+ dst_hold(&net->ipv6.ip6_null_entry->dst); -+ return &net->ipv6.ip6_null_entry->dst; - } - - static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, -@@ -116,7 +105,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, - flp6->saddr = saddr; - } - err = rt->dst.error; -- goto out; -+ if (err != -EAGAIN) -+ goto out; - } - again: - ip6_rt_put(rt); -diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c -index 85bf86458706..1ac06723f0d7 100644 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -290,8 +290,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, - struct rt6_info *rt; - - rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); -- if (rt->rt6i_flags & RTF_REJECT && -- rt->dst.error == -EAGAIN) { -+ if (rt->dst.error == -EAGAIN) { - ip6_rt_put(rt); - rt = net->ipv6.ip6_null_entry; - dst_hold(&rt->dst); -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 19c0d67ce8c4..7d339fc1057f 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1005,8 +1005,10 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, - } - #endif - if (ipv6_addr_v4mapped(&fl6->saddr) && -- !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) -- return -EAFNOSUPPORT; -+ !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) { -+ err = -EAFNOSUPPORT; -+ goto out_err_release; -+ } - - return 0; - -diff --git a/net/key/af_key.c b/net/key/af_key.c -index f9c9ecb0cdd3..e67c28e614b9 100644 ---- a/net/key/af_key.c -+++ b/net/key/af_key.c -@@ -1135,6 +1135,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, - goto out; - } - -+ err = -ENOBUFS; - key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; - if (sa->sadb_sa_auth) { - int keysize = 0; -@@ -1146,8 +1147,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, - if (key) - keysize = (key->sadb_key_bits + 7) / 8; - x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); -- if (!x->aalg) -+ if (!x->aalg) { -+ err = -ENOMEM; - goto out; -+ } - strcpy(x->aalg->alg_name, a->name); - x->aalg->alg_key_len = 0; - if (key) { -@@ -1166,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, - goto out; - } - x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); -- if (!x->calg) -+ if (!x->calg) { -+ err = -ENOMEM; - goto out; -+ } - strcpy(x->calg->alg_name, a->name); - x->props.calgo = sa->sadb_sa_encrypt; - } else { -@@ -1181,8 +1186,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, - if (key) - keysize = (key->sadb_key_bits + 7) / 8; - x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); -- if (!x->ealg) -+ if (!x->ealg) { -+ err = -ENOMEM; - goto out; -+ } - strcpy(x->ealg->alg_name, a->name); - x->ealg->alg_key_len = 0; - if (key) { -@@ -1227,8 +1234,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, - struct xfrm_encap_tmpl *natt; - - x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL); -- if (!x->encap) -+ if (!x->encap) { -+ err = -ENOMEM; - goto out; -+ } - - natt = x->encap; - n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; -diff --git a/net/mac80211/main.c b/net/mac80211/main.c -index 175ffcf7fb06..2ee53dc1ddf7 100644 ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -891,12 +891,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) - supp_ht = supp_ht || sband->ht_cap.ht_supported; - supp_vht = supp_vht || sband->vht_cap.vht_supported; - -- if (sband->ht_cap.ht_supported) -- local->rx_chains = -- max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), -- local->rx_chains); -+ if (!sband->ht_cap.ht_supported) -+ continue; - - /* TODO: consider VHT for RX chains, hopefully it's the same */ -+ local->rx_chains = -+ max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), -+ local->rx_chains); -+ -+ /* no need to mask, SM_PS_DISABLED has all bits set */ -+ sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED << -+ IEEE80211_HT_CAP_SM_PS_SHIFT; - } - - /* if low-level driver supports AP, we also support VLAN */ -diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c -index 9f5272968abb..e565b2becb14 100644 ---- a/net/netfilter/nf_conntrack_netlink.c -+++ b/net/netfilter/nf_conntrack_netlink.c -@@ -45,6 +45,8 @@ - #include - #include - #include -+#include -+#include - #ifdef CONFIG_NF_NAT_NEEDED - #include - #include -@@ -1798,6 +1800,8 @@ ctnetlink_create_conntrack(struct net *net, - nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); - nf_ct_labels_ext_add(ct); -+ nfct_seqadj_ext_add(ct); -+ nfct_synproxy_ext_add(ct); - - /* we must add conntrack extensions before confirmation. */ - ct->status |= IPS_CONFIRMED; -diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c -index b7c43def0dc6..00f798b20b20 100644 ---- a/net/netfilter/xt_TCPMSS.c -+++ b/net/netfilter/xt_TCPMSS.c -@@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - tcp_hdrlen = tcph->doff * 4; - -- if (len < tcp_hdrlen) -+ if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) - return -1; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU) { -@@ -156,6 +156,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, - if (len > tcp_hdrlen) - return 0; - -+ /* tcph->doff has 4 bits, do not wrap it to 0 */ -+ if (tcp_hdrlen >= 15 * 4) -+ return 0; -+ - /* - * MSS Option not found ?! add it.. - */ -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 956141b71619..3ebf3b652d60 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -239,7 +239,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, - union sctp_addr *laddr = (union sctp_addr *)addr; - struct sctp_transport *transport; - -- if (sctp_verify_addr(sk, laddr, af->sockaddr_len)) -+ if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len)) - return NULL; - - addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c -index b2e934ff2448..e05ec54ac53f 100644 ---- a/net/unix/af_unix.c -+++ b/net/unix/af_unix.c -@@ -997,7 +997,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) - struct path path = { NULL, NULL }; - - err = -EINVAL; -- if (sunaddr->sun_family != AF_UNIX) -+ if (addr_len < offsetofend(struct sockaddr_un, sun_family) || -+ sunaddr->sun_family != AF_UNIX) - goto out; - - if (addr_len == sizeof(short)) { -@@ -1108,6 +1109,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, - unsigned int hash; - int err; - -+ err = -EINVAL; -+ if (alen < offsetofend(struct sockaddr, sa_family)) -+ goto out; -+ - if (addr->sa_family != AF_UNSPEC) { - err = unix_mkname(sunaddr, alen, &hash); - if (err < 0) -diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c -index 36a50ef9295d..8a0fdd870395 100644 ---- a/net/xfrm/xfrm_policy.c -+++ b/net/xfrm/xfrm_policy.c -@@ -1776,43 +1776,6 @@ free_dst: - goto out; - } - --#ifdef CONFIG_XFRM_SUB_POLICY --static int xfrm_dst_alloc_copy(void **target, const void *src, int size) --{ -- if (!*target) { -- *target = kmalloc(size, GFP_ATOMIC); -- if (!*target) -- return -ENOMEM; -- } -- -- memcpy(*target, src, size); -- return 0; --} --#endif -- --static int xfrm_dst_update_parent(struct dst_entry *dst, -- const struct xfrm_selector *sel) --{ --#ifdef CONFIG_XFRM_SUB_POLICY -- struct xfrm_dst *xdst = (struct xfrm_dst *)dst; -- return xfrm_dst_alloc_copy((void **)&(xdst->partner), -- sel, sizeof(*sel)); --#else -- return 0; --#endif --} -- --static int xfrm_dst_update_origin(struct dst_entry *dst, -- const struct flowi *fl) --{ --#ifdef CONFIG_XFRM_SUB_POLICY -- struct xfrm_dst *xdst = (struct xfrm_dst *)dst; -- return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); --#else -- return 0; --#endif --} -- - static int xfrm_expand_policies(const struct flowi *fl, u16 family, - struct xfrm_policy **pols, - int *num_pols, int *num_xfrms) -@@ -1884,16 +1847,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, - - xdst = (struct xfrm_dst *)dst; - xdst->num_xfrms = err; -- if (num_pols > 1) -- err = xfrm_dst_update_parent(dst, &pols[1]->selector); -- else -- err = xfrm_dst_update_origin(dst, fl); -- if (unlikely(err)) { -- dst_free(dst); -- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); -- return ERR_PTR(err); -- } -- - xdst->num_pols = num_pols; - memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); - xdst->policy_genid = atomic_read(&pols[0]->genid); -diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h -index 373fcad840ea..776dffa88aee 100644 ---- a/sound/pci/hda/hda_codec.h -+++ b/sound/pci/hda/hda_codec.h -@@ -294,6 +294,8 @@ struct hda_codec { - - #define list_for_each_codec(c, bus) \ - list_for_each_entry(c, &(bus)->core.codec_list, core.list) -+#define list_for_each_codec_safe(c, n, bus) \ -+ list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list) - - /* snd_hda_codec_read/write optional flags */ - #define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0) -diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c -index 5baf8b56b6e7..9c6e10fb479f 100644 ---- a/sound/pci/hda/hda_controller.c -+++ b/sound/pci/hda/hda_controller.c -@@ -1128,8 +1128,12 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs); - /* configure each codec instance */ - int azx_codec_configure(struct azx *chip) - { -- struct hda_codec *codec; -- list_for_each_codec(codec, &chip->bus) { -+ struct hda_codec *codec, *next; -+ -+ /* use _safe version here since snd_hda_codec_configure() deregisters -+ * the device upon error and deletes itself from the bus list. -+ */ -+ list_for_each_codec_safe(codec, next, &chip->bus) { - snd_hda_codec_configure(codec); - } - return 0; -diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c -index dc2fa576d60d..689df78f640a 100644 ---- a/sound/pci/hda/hda_generic.c -+++ b/sound/pci/hda/hda_generic.c -@@ -3190,6 +3190,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec) - spec->input_paths[i][nums]); - spec->input_paths[i][nums] = - spec->input_paths[i][n]; -+ spec->input_paths[i][n] = 0; - } - } - nums++; -diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c -index 05012bb178d7..fdd87c7e3e91 100644 ---- a/tools/perf/util/probe-finder.c -+++ b/tools/perf/util/probe-finder.c -@@ -1460,16 +1460,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, - Dwarf_Addr _addr = 0, baseaddr = 0; - const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; - int baseline = 0, lineno = 0, ret = 0; -- bool reloc = false; - --retry: -+ /* We always need to relocate the address for aranges */ -+ if (debuginfo__get_text_offset(dbg, &baseaddr) == 0) -+ addr += baseaddr; - /* Find cu die */ - if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { -- if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { -- addr += baseaddr; -- reloc = true; -- goto retry; -- } - pr_warning("Failed to find debug information for address %lx\n", - addr); - ret = -EINVAL; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.76-77.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.76-77.patch deleted file mode 100644 index 5fa837fbb..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.76-77.patch +++ /dev/null @@ -1,1544 +0,0 @@ -diff --git a/Makefile b/Makefile -index 902ab134446e..bf49a61d02e2 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 76 -+SUBLEVEL = 77 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h -index 0b1ff4c1c14e..fffb2794dd89 100644 ---- a/arch/x86/include/asm/pat.h -+++ b/arch/x86/include/asm/pat.h -@@ -7,6 +7,7 @@ - bool pat_enabled(void); - void pat_disable(const char *reason); - extern void pat_init(void); -+extern void init_cache_modes(void); - - extern int reserve_memtype(u64 start, u64 end, - enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm); -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index d2bbe343fda7..e67b834279b2 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -1048,6 +1048,13 @@ void __init setup_arch(char **cmdline_p) - if (mtrr_trim_uncached_memory(max_pfn)) - max_pfn = e820_end_of_ram_pfn(); - -+ /* -+ * This call is required when the CPU does not support PAT. If -+ * mtrr_bp_init() invoked it already via pat_init() the call has no -+ * effect. -+ */ -+ init_cache_modes(); -+ - #ifdef CONFIG_X86_32 - /* max_low_pfn get updated here */ - find_low_pfn_range(); -diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S -index 27f89c79a44b..423644c230e7 100644 ---- a/arch/x86/lib/copy_user_64.S -+++ b/arch/x86/lib/copy_user_64.S -@@ -80,7 +80,7 @@ ENTRY(copy_user_generic_unrolled) - movl %edx,%ecx - andl $63,%edx - shrl $6,%ecx -- jz 17f -+ jz .L_copy_short_string - 1: movq (%rsi),%r8 - 2: movq 1*8(%rsi),%r9 - 3: movq 2*8(%rsi),%r10 -@@ -101,7 +101,8 @@ ENTRY(copy_user_generic_unrolled) - leaq 64(%rdi),%rdi - decl %ecx - jnz 1b --17: movl %edx,%ecx -+.L_copy_short_string: -+ movl %edx,%ecx - andl $7,%edx - shrl $3,%ecx - jz 20f -@@ -215,6 +216,8 @@ ENDPROC(copy_user_generic_string) - */ - ENTRY(copy_user_enhanced_fast_string) - ASM_STAC -+ cmpl $64,%edx -+ jb .L_copy_short_string /* less then 64 bytes, avoid the costly 'rep' */ - movl %edx,%ecx - 1: rep - movsb -diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c -index 6ad687d104ca..3f1bb4f93a5a 100644 ---- a/arch/x86/mm/pat.c -+++ b/arch/x86/mm/pat.c -@@ -36,14 +36,14 @@ - #undef pr_fmt - #define pr_fmt(fmt) "" fmt - --static bool boot_cpu_done; -- --static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT); --static void init_cache_modes(void); -+static bool __read_mostly boot_cpu_done; -+static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT); -+static bool __read_mostly pat_initialized; -+static bool __read_mostly init_cm_done; - - void pat_disable(const char *reason) - { -- if (!__pat_enabled) -+ if (pat_disabled) - return; - - if (boot_cpu_done) { -@@ -51,10 +51,8 @@ void pat_disable(const char *reason) - return; - } - -- __pat_enabled = 0; -+ pat_disabled = true; - pr_info("x86/PAT: %s\n", reason); -- -- init_cache_modes(); - } - - static int __init nopat(char *str) -@@ -66,7 +64,7 @@ early_param("nopat", nopat); - - bool pat_enabled(void) - { -- return !!__pat_enabled; -+ return pat_initialized; - } - EXPORT_SYMBOL_GPL(pat_enabled); - -@@ -204,6 +202,8 @@ static void __init_cache_modes(u64 pat) - update_cache_mode_entry(i, cache); - } - pr_info("x86/PAT: Configuration [0-7]: %s\n", pat_msg); -+ -+ init_cm_done = true; - } - - #define PAT(x, y) ((u64)PAT_ ## y << ((x)*8)) -@@ -224,6 +224,7 @@ static void pat_bsp_init(u64 pat) - } - - wrmsrl(MSR_IA32_CR_PAT, pat); -+ pat_initialized = true; - - __init_cache_modes(pat); - } -@@ -241,10 +242,9 @@ static void pat_ap_init(u64 pat) - wrmsrl(MSR_IA32_CR_PAT, pat); - } - --static void init_cache_modes(void) -+void init_cache_modes(void) - { - u64 pat = 0; -- static int init_cm_done; - - if (init_cm_done) - return; -@@ -286,8 +286,6 @@ static void init_cache_modes(void) - } - - __init_cache_modes(pat); -- -- init_cm_done = 1; - } - - /** -@@ -305,10 +303,8 @@ void pat_init(void) - u64 pat; - struct cpuinfo_x86 *c = &boot_cpu_data; - -- if (!pat_enabled()) { -- init_cache_modes(); -+ if (pat_disabled) - return; -- } - - if ((c->x86_vendor == X86_VENDOR_INTEL) && - (((c->x86 == 0x6) && (c->x86_model <= 0xd)) || -diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c -index 0c2fae8d929d..73eb7fd4aec4 100644 ---- a/arch/x86/tools/relocs.c -+++ b/arch/x86/tools/relocs.c -@@ -992,11 +992,12 @@ static void emit_relocs(int as_text, int use_real_mode) - die("Segment relocations found but --realmode not specified\n"); - - /* Order the relocations for more efficient processing */ -- sort_relocs(&relocs16); - sort_relocs(&relocs32); - #if ELF_BITS == 64 - sort_relocs(&relocs32neg); - sort_relocs(&relocs64); -+#else -+ sort_relocs(&relocs16); - #endif - - /* Print the relocations */ -diff --git a/drivers/base/platform.c b/drivers/base/platform.c -index ba66330cea67..cb4ad6e98b28 100644 ---- a/drivers/base/platform.c -+++ b/drivers/base/platform.c -@@ -807,7 +807,7 @@ static ssize_t driver_override_store(struct device *dev, - const char *buf, size_t count) - { - struct platform_device *pdev = to_platform_device(dev); -- char *driver_override, *old = pdev->driver_override, *cp; -+ char *driver_override, *old, *cp; - - if (count > PATH_MAX) - return -EINVAL; -@@ -820,12 +820,15 @@ static ssize_t driver_override_store(struct device *dev, - if (cp) - *cp = '\0'; - -+ device_lock(dev); -+ old = pdev->driver_override; - if (strlen(driver_override)) { - pdev->driver_override = driver_override; - } else { - kfree(driver_override); - pdev->driver_override = NULL; - } -+ device_unlock(dev); - - kfree(old); - -@@ -836,8 +839,12 @@ static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) - { - struct platform_device *pdev = to_platform_device(dev); -+ ssize_t len; - -- return sprintf(buf, "%s\n", pdev->driver_override); -+ device_lock(dev); -+ len = sprintf(buf, "%s\n", pdev->driver_override); -+ device_unlock(dev); -+ return len; - } - static DEVICE_ATTR_RW(driver_override); - -diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c -index f300eba95bb1..1244cdf52859 100644 ---- a/drivers/gpu/drm/virtio/virtgpu_object.c -+++ b/drivers/gpu/drm/virtio/virtgpu_object.c -@@ -81,8 +81,10 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, - return -ENOMEM; - size = roundup(size, PAGE_SIZE); - ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size); -- if (ret != 0) -+ if (ret != 0) { -+ kfree(bo); - return ret; -+ } - bo->dumb = false; - virtio_gpu_init_ttm_placement(bo, pinned); - -diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c -index 1c02deab068f..9eca4b41fa0a 100644 ---- a/drivers/infiniband/core/uverbs_cmd.c -+++ b/drivers/infiniband/core/uverbs_cmd.c -@@ -2287,6 +2287,10 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; - -+ if (cmd.port_num < rdma_start_port(ib_dev) || -+ cmd.port_num > rdma_end_port(ib_dev)) -+ return -EINVAL; -+ - INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, - out_len); - -@@ -2827,6 +2831,10 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; - -+ if (cmd.attr.port_num < rdma_start_port(ib_dev) || -+ cmd.attr.port_num > rdma_end_port(ib_dev)) -+ return -EINVAL; -+ - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) - return -ENOMEM; -diff --git a/drivers/md/md.c b/drivers/md/md.c -index eff554a12fb4..0a856cb181e9 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -1866,7 +1866,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) - } - sb = page_address(rdev->sb_page); - sb->data_size = cpu_to_le64(num_sectors); -- sb->super_offset = rdev->sb_start; -+ sb->super_offset = cpu_to_le64(rdev->sb_start); - sb->sb_csum = calc_sb_1_csum(sb); - md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, - rdev->sb_page); -@@ -2273,7 +2273,7 @@ static bool does_sb_need_changing(struct mddev *mddev) - /* Check if any mddev parameters have changed */ - if ((mddev->dev_sectors != le64_to_cpu(sb->size)) || - (mddev->reshape_position != le64_to_cpu(sb->reshape_position)) || -- (mddev->layout != le64_to_cpu(sb->layout)) || -+ (mddev->layout != le32_to_cpu(sb->layout)) || - (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) || - (mddev->chunk_sectors != le32_to_cpu(sb->chunksize))) - return true; -diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c -index 8ef6399d794f..bc957528f69f 100644 ---- a/drivers/media/pci/saa7134/saa7134-i2c.c -+++ b/drivers/media/pci/saa7134/saa7134-i2c.c -@@ -355,12 +355,43 @@ static struct i2c_client saa7134_client_template = { - - /* ----------------------------------------------------------- */ - -+/* On Medion 7134 reading EEPROM needs DVB-T demod i2c gate open */ -+static void saa7134_i2c_eeprom_md7134_gate(struct saa7134_dev *dev) -+{ -+ u8 subaddr = 0x7, dmdregval; -+ u8 data[2]; -+ int ret; -+ struct i2c_msg i2cgatemsg_r[] = { {.addr = 0x08, .flags = 0, -+ .buf = &subaddr, .len = 1}, -+ {.addr = 0x08, -+ .flags = I2C_M_RD, -+ .buf = &dmdregval, .len = 1} -+ }; -+ struct i2c_msg i2cgatemsg_w[] = { {.addr = 0x08, .flags = 0, -+ .buf = data, .len = 2} }; -+ -+ ret = i2c_transfer(&dev->i2c_adap, i2cgatemsg_r, 2); -+ if ((ret == 2) && (dmdregval & 0x2)) { -+ pr_debug("%s: DVB-T demod i2c gate was left closed\n", -+ dev->name); -+ -+ data[0] = subaddr; -+ data[1] = (dmdregval & ~0x2); -+ if (i2c_transfer(&dev->i2c_adap, i2cgatemsg_w, 1) != 1) -+ pr_err("%s: EEPROM i2c gate open failure\n", -+ dev->name); -+ } -+} -+ - static int - saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len) - { - unsigned char buf; - int i,err; - -+ if (dev->board == SAA7134_BOARD_MD7134) -+ saa7134_i2c_eeprom_md7134_gate(dev); -+ - dev->i2c_client.addr = 0xa0 >> 1; - buf = 0; - if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) { -diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c -index 70da30095b89..a5e4b4b93d1b 100644 ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -1583,6 +1583,11 @@ static int bgmac_probe(struct bcma_device *core) - dev_warn(&core->dev, "Using random MAC: %pM\n", mac); - } - -+ /* This (reset &) enable is not preset in specs or reference driver but -+ * Broadcom does it in arch PCI code when enabling fake PCI device. -+ */ -+ bcma_core_enable(core, 0); -+ - /* Allocation and references */ - net_dev = alloc_etherdev(sizeof(*bgmac)); - if (!net_dev) -diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c -index 930785a724e1..907fd60c4241 100644 ---- a/drivers/net/wireless/ath/ath10k/pci.c -+++ b/drivers/net/wireless/ath/ath10k/pci.c -@@ -3050,7 +3050,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, - goto err_core_destroy; - } - -- if (QCA_REV_6174(ar)) -+ if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) - ath10k_pci_override_ce_config(ar); - - ret = ath10k_pci_alloc_pipes(ar); -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index d59769e858f4..019d7165a045 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -2539,7 +2539,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, - - tasklet_hrtimer_init(&data->beacon_timer, - mac80211_hwsim_beacon, -- CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); -+ CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - - spin_lock_bh(&hwsim_radio_lock); - list_add_tail(&data->list, &hwsim_radios); -diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c -index 6bbda6b4ab50..5da9c95dccb7 100644 ---- a/drivers/pinctrl/freescale/pinctrl-mxs.c -+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c -@@ -195,6 +195,16 @@ static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, - return 0; - } - -+static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg) -+{ -+ u32 tmp; -+ -+ tmp = readl(reg); -+ tmp &= ~(mask << shift); -+ tmp |= value << shift; -+ writel(tmp, reg); -+} -+ - static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group) - { -@@ -212,8 +222,7 @@ static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, - reg += bank * 0x20 + pin / 16 * 0x10; - shift = pin % 16 * 2; - -- writel(0x3 << shift, reg + CLR); -- writel(g->muxsel[i] << shift, reg + SET); -+ mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg); - } - - return 0; -@@ -280,8 +289,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev, - /* mA */ - if (config & MA_PRESENT) { - shift = pin % 8 * 4; -- writel(0x3 << shift, reg + CLR); -- writel(ma << shift, reg + SET); -+ mxs_pinctrl_rmwl(ma, 0x3, shift, reg); - } - - /* vol */ -diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c -index 9677807db364..b505b87661f8 100644 ---- a/drivers/pinctrl/meson/pinctrl-meson8b.c -+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c -@@ -732,8 +732,8 @@ static const char * const sdxc_c_groups[] = { - static const char * const nand_groups[] = { - "nand_io", "nand_io_ce0", "nand_io_ce1", - "nand_io_rb0", "nand_ale", "nand_cle", -- "nand_wen_clk", "nand_ren_clk", "nand_dqs0", -- "nand_dqs1" -+ "nand_wen_clk", "nand_ren_clk", "nand_dqs_0", -+ "nand_dqs_1" - }; - - static const char * const nor_groups[] = { -diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c -index 2b0d70217bbd..699efb1a8c45 100644 ---- a/drivers/pinctrl/sh-pfc/core.c -+++ b/drivers/pinctrl/sh-pfc/core.c -@@ -543,6 +543,9 @@ static int sh_pfc_probe(struct platform_device *pdev) - ret = info->ops->init(pfc); - if (ret < 0) - return ret; -+ -+ /* .init() may have overridden pfc->info */ -+ info = pfc->info; - } - - /* Enable dummy states for those platforms without pinctrl support */ -diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c -index 87a4f44147c1..42ffa8708abc 100644 ---- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c -+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c -@@ -1102,7 +1102,7 @@ static const u16 pinmux_data[] = { - PINMUX_IPSR_MSEL(IP6_5_3, FMIN_E, SEL_FM_4), - PINMUX_IPSR_DATA(IP6_7_6, AUDIO_CLKOUT), - PINMUX_IPSR_MSEL(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1), -- PINMUX_IPSR_MSEL(IP6_5_3, TX2, SEL_SCIF2_0), -+ PINMUX_IPSR_MSEL(IP6_7_6, TX2, SEL_SCIF2_0), - PINMUX_IPSR_MSEL(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0), - PINMUX_IPSR_DATA(IP6_9_8, IRQ0), - PINMUX_IPSR_MSEL(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3), -diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c -index 90b973e15982..a7c81e988656 100644 ---- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c -@@ -394,7 +394,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = { - SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18), - SUNXI_FUNCTION(0x0, "gpio_in"), - SUNXI_FUNCTION(0x1, "gpio_out"), -- SUNXI_FUNCTION(0x3, "owa")), /* DOUT */ -+ SUNXI_FUNCTION(0x3, "spdif")), /* DOUT */ - SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19), - SUNXI_FUNCTION(0x0, "gpio_in"), - SUNXI_FUNCTION(0x1, "gpio_out")), -diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c -index 7b4af519e17e..8fed55342b0f 100644 ---- a/drivers/staging/comedi/comedi_fops.c -+++ b/drivers/staging/comedi/comedi_fops.c -@@ -2911,6 +2911,7 @@ static int __init comedi_init(void) - dev = comedi_alloc_board_minor(NULL); - if (IS_ERR(dev)) { - comedi_cleanup_board_minors(); -+ class_destroy(comedi_class); - cdev_del(&comedi_cdev); - unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), - COMEDI_NUM_MINORS); -diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c -index 01e642db311e..f35ee85f61b5 100644 ---- a/drivers/staging/vt6656/main_usb.c -+++ b/drivers/staging/vt6656/main_usb.c -@@ -529,6 +529,9 @@ static int vnt_start(struct ieee80211_hw *hw) - goto free_all; - } - -+ if (vnt_key_init_table(priv)) -+ goto free_all; -+ - priv->int_interval = 1; /* bInterval is set to 1 */ - - vnt_int_start_interrupt(priv); -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 96b21b0dac1e..3116edfcdc18 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -223,6 +223,10 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Blackmagic Design UltraStudio SDI */ - { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, - -+ /* Hauppauge HVR-950q */ -+ { USB_DEVICE(0x2040, 0x7200), .driver_info = -+ USB_QUIRK_CONFIG_INTF_STRINGS }, -+ - /* INTEL VALUE SSD */ - { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, - -diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c -index 5c0adb9c6fb2..81db2fa08cad 100644 ---- a/drivers/usb/dwc3/dwc3-st.c -+++ b/drivers/usb/dwc3/dwc3-st.c -@@ -224,7 +224,7 @@ static int st_dwc3_probe(struct platform_device *pdev) - - dwc3_data->syscfg_reg_off = res->start; - -- dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n", -+ dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n", - dwc3_data->glue_base, dwc3_data->syscfg_reg_off); - - dwc3_data->rstc_pwrdn = devm_reset_control_get(dev, "powerdown"); -diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c -index 33cec50978b8..b0dc6da3d970 100644 ---- a/drivers/usb/serial/cp210x.c -+++ b/drivers/usb/serial/cp210x.c -@@ -134,6 +134,7 @@ static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ - { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ - { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ -+ { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ - { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index 3bf61acfc26b..ebe51f11105d 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -1877,6 +1877,10 @@ static const struct usb_device_id option_ids[] = { - .driver_info = (kernel_ulong_t)&four_g_w100_blacklist - }, - { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) }, -+ { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9801, 0xff), -+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, -+ { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff), -+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, - { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, - { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, -diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c -index fd509ed6cf70..652b4334b26d 100644 ---- a/drivers/usb/serial/qcserial.c -+++ b/drivers/usb/serial/qcserial.c -@@ -158,6 +158,7 @@ static const struct usb_device_id id_table[] = { - {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ - {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ - {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */ -+ {DEVICE_SWI(0x1199, 0x9063)}, /* Sierra Wireless EM7305 */ - {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */ - {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ - {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */ -diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c -index 44ab43fc4fcc..af10f7b131a4 100644 ---- a/drivers/usb/usbip/stub_main.c -+++ b/drivers/usb/usbip/stub_main.c -@@ -262,7 +262,11 @@ void stub_device_cleanup_urbs(struct stub_device *sdev) - kmem_cache_free(stub_priv_cache, priv); - - kfree(urb->transfer_buffer); -+ urb->transfer_buffer = NULL; -+ - kfree(urb->setup_packet); -+ urb->setup_packet = NULL; -+ - usb_free_urb(urb); - } - } -diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c -index dbcabc9dbe0d..021003c4de53 100644 ---- a/drivers/usb/usbip/stub_tx.c -+++ b/drivers/usb/usbip/stub_tx.c -@@ -28,7 +28,11 @@ static void stub_free_priv_and_urb(struct stub_priv *priv) - struct urb *urb = priv->urb; - - kfree(urb->setup_packet); -+ urb->setup_packet = NULL; -+ - kfree(urb->transfer_buffer); -+ urb->transfer_buffer = NULL; -+ - list_del(&priv->list); - kmem_cache_free(stub_priv_cache, priv); - usb_free_urb(urb); -diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c -index 5d09ea585840..c2ee23acf359 100644 ---- a/fs/ext4/sysfs.c -+++ b/fs/ext4/sysfs.c -@@ -100,7 +100,7 @@ static ssize_t reserved_clusters_store(struct ext4_attr *a, - int ret; - - ret = kstrtoull(skip_spaces(buf), 0, &val); -- if (!ret || val >= clusters) -+ if (ret || val >= clusters) - return -EINVAL; - - atomic64_set(&sbi->s_resv_clusters, val); -diff --git a/fs/fcntl.c b/fs/fcntl.c -index ee85cd4e136a..62376451bbce 100644 ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -740,16 +740,10 @@ static int __init fcntl_init(void) - * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY - * is defined as O_NONBLOCK on some platforms and not on others. - */ -- BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( -- O_RDONLY | O_WRONLY | O_RDWR | -- O_CREAT | O_EXCL | O_NOCTTY | -- O_TRUNC | O_APPEND | /* O_NONBLOCK | */ -- __O_SYNC | O_DSYNC | FASYNC | -- O_DIRECT | O_LARGEFILE | O_DIRECTORY | -- O_NOFOLLOW | O_NOATIME | O_CLOEXEC | -- __FMODE_EXEC | O_PATH | __O_TMPFILE | -- __FMODE_NONOTIFY -- )); -+ BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != -+ HWEIGHT32( -+ (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) | -+ __FMODE_EXEC | __FMODE_NONOTIFY)); - - fasync_cache = kmem_cache_create("fasync_cache", - sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL); -diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c -index 9cd8c92b953d..070901e76653 100644 ---- a/fs/gfs2/glock.c -+++ b/fs/gfs2/glock.c -@@ -80,9 +80,9 @@ static struct rhashtable_params ht_parms = { - - static struct rhashtable gl_hash_table; - --void gfs2_glock_free(struct gfs2_glock *gl) -+static void gfs2_glock_dealloc(struct rcu_head *rcu) - { -- struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; -+ struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu); - - if (gl->gl_ops->go_flags & GLOF_ASPACE) { - kmem_cache_free(gfs2_glock_aspace_cachep, gl); -@@ -90,6 +90,13 @@ void gfs2_glock_free(struct gfs2_glock *gl) - kfree(gl->gl_lksb.sb_lvbptr); - kmem_cache_free(gfs2_glock_cachep, gl); - } -+} -+ -+void gfs2_glock_free(struct gfs2_glock *gl) -+{ -+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; -+ -+ call_rcu(&gl->gl_rcu, gfs2_glock_dealloc); - if (atomic_dec_and_test(&sdp->sd_glock_disposal)) - wake_up(&sdp->sd_glock_wait); - } -diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h -index be519416c112..4a9077ec9313 100644 ---- a/fs/gfs2/incore.h -+++ b/fs/gfs2/incore.h -@@ -367,6 +367,7 @@ struct gfs2_glock { - loff_t end; - } gl_vm; - }; -+ struct rcu_head gl_rcu; - struct rhash_head gl_node; - }; - -diff --git a/fs/open.c b/fs/open.c -index 157b9940dd73..fbc5c7b230b3 100644 ---- a/fs/open.c -+++ b/fs/open.c -@@ -885,6 +885,12 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o - int lookup_flags = 0; - int acc_mode; - -+ /* -+ * Clear out all open flags we don't know about so that we don't report -+ * them in fcntl(F_GETFD) or similar interfaces. -+ */ -+ flags &= VALID_OPEN_FLAGS; -+ - if (flags & (O_CREAT | __O_TMPFILE)) - op->mode = (mode & S_IALLUGO) | S_IFREG; - else -diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h -index 76ce329e656d..1b48d9c9a561 100644 ---- a/include/linux/fcntl.h -+++ b/include/linux/fcntl.h -@@ -3,6 +3,12 @@ - - #include - -+/* list of all valid flags for the open/openat flags argument: */ -+#define VALID_OPEN_FLAGS \ -+ (O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ -+ O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \ -+ FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \ -+ O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE) - - #ifndef force_o_largefile - #define force_o_largefile() (BITS_PER_LONG != 32) -diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h -index 3993b21f3d11..757c554408ce 100644 ---- a/include/linux/usb/hcd.h -+++ b/include/linux/usb/hcd.h -@@ -560,9 +560,9 @@ extern void usb_ep0_reinit(struct usb_device *); - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) - - #define EndpointRequest \ -- ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -+ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) - #define EndpointOutRequest \ -- ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -+ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) - - /* class requests from the USB 2.0 hub spec, table 11-15 */ - /* GetBusState and SetHubDescriptor are optional, omitted */ -diff --git a/ipc/mqueue.c b/ipc/mqueue.c -index 161a1807e6ef..5e24eb0ab5dd 100644 ---- a/ipc/mqueue.c -+++ b/ipc/mqueue.c -@@ -1251,8 +1251,10 @@ retry: - - timeo = MAX_SCHEDULE_TIMEOUT; - ret = netlink_attachskb(sock, nc, &timeo, NULL); -- if (ret == 1) -+ if (ret == 1) { -+ sock = NULL; - goto retry; -+ } - if (ret) { - sock = NULL; - nc = NULL; -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 464a7864e4c5..002ec084124b 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -2067,9 +2067,12 @@ static int do_proc_douintvec_conv(bool *negp, unsigned long *lvalp, - if (write) { - if (*negp) - return -EINVAL; -+ if (*lvalp > UINT_MAX) -+ return -EINVAL; - *valp = *lvalp; - } else { - unsigned int val = *valp; -+ *negp = false; - *lvalp = (unsigned long)val; - } - return 0; -diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c -index 12ea4ea619ee..e9092a0247bf 100644 ---- a/kernel/trace/trace_kprobe.c -+++ b/kernel/trace/trace_kprobe.c -@@ -659,30 +659,25 @@ static int create_trace_kprobe(int argc, char **argv) - pr_info("Probe point is not specified.\n"); - return -EINVAL; - } -- if (isdigit(argv[1][0])) { -- if (is_return) { -- pr_info("Return probe point must be a symbol.\n"); -- return -EINVAL; -- } -- /* an address specified */ -- ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr); -- if (ret) { -- pr_info("Failed to parse address.\n"); -- return ret; -- } -- } else { -+ -+ /* try to parse an address. if that fails, try to read the -+ * input as a symbol. */ -+ if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) { - /* a symbol specified */ - symbol = argv[1]; - /* TODO: support .init module functions */ - ret = traceprobe_split_symbol_offset(symbol, &offset); - if (ret) { -- pr_info("Failed to parse symbol.\n"); -+ pr_info("Failed to parse either an address or a symbol.\n"); - return ret; - } - if (offset && is_return) { - pr_info("Return probe must be used without offset.\n"); - return -EINVAL; - } -+ } else if (is_return) { -+ pr_info("Return probe point must be a symbol.\n"); -+ return -EINVAL; - } - argc -= 2; argv += 2; - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index bfc5050cbd01..440c2df9be82 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2529,7 +2529,7 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc) - if (!populated_zone(zone)) - continue; - -- classzone_idx = requested_highidx; -+ classzone_idx = gfp_zone(sc->gfp_mask); - while (!populated_zone(zone->zone_pgdat->node_zones + - classzone_idx)) - classzone_idx--; -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 87791f803627..8f13b2eaabf8 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -2165,8 +2165,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) - { - struct tcp_sock *tp = tcp_sk(sk); - struct sk_buff *skb; -- int cnt, oldcnt; -- int err; -+ int cnt, oldcnt, lost; - unsigned int mss; - /* Use SACK to deduce losses of new sequences sent during recovery */ - const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; -@@ -2206,9 +2205,10 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) - break; - - mss = tcp_skb_mss(skb); -- err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, -- mss, GFP_ATOMIC); -- if (err < 0) -+ /* If needed, chop off the prefix to mark as lost. */ -+ lost = (packets - oldcnt) * mss; -+ if (lost < skb->len && -+ tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0) - break; - cnt = packets; - } -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 696ccfa08d10..31898856682e 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -428,7 +428,7 @@ static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key, - static struct key *request_master_key(struct encrypted_key_payload *epayload, - const u8 **master_key, size_t *master_keylen) - { -- struct key *mkey = NULL; -+ struct key *mkey = ERR_PTR(-EINVAL); - - if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX, - KEY_TRUSTED_PREFIX_LEN)) { -diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h -index fa7208a32d76..8a679b21f0c4 100644 ---- a/tools/include/linux/compiler.h -+++ b/tools/include/linux/compiler.h -@@ -115,4 +115,13 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s - #define WRITE_ONCE(x, val) \ - ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) - -+ -+#ifndef __fallthrough -+# if defined(__GNUC__) && __GNUC__ >= 7 -+# define __fallthrough __attribute__ ((fallthrough)) -+# else -+# define __fallthrough -+# endif -+#endif -+ - #endif /* _TOOLS_LINUX_COMPILER_H */ -diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c -index d28c1b6a3b54..fa5d17af88b7 100644 ---- a/tools/perf/arch/x86/tests/intel-cqm.c -+++ b/tools/perf/arch/x86/tests/intel-cqm.c -@@ -17,7 +17,7 @@ static pid_t spawn(void) - if (pid) - return pid; - -- while(1); -+ while(1) - sleep(5); - return 0; - } -diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c -index 9223c164e545..1f86ee8fb831 100644 ---- a/tools/perf/arch/x86/util/dwarf-regs.c -+++ b/tools/perf/arch/x86/util/dwarf-regs.c -@@ -63,6 +63,8 @@ struct pt_regs_offset { - # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} - #endif - -+/* TODO: switching by dwarf address size */ -+#ifndef __x86_64__ - static const struct pt_regs_offset x86_32_regoffset_table[] = { - REG_OFFSET_NAME_32("%ax", eax), - REG_OFFSET_NAME_32("%cx", ecx), -@@ -75,6 +77,8 @@ static const struct pt_regs_offset x86_32_regoffset_table[] = { - REG_OFFSET_END, - }; - -+#define regoffset_table x86_32_regoffset_table -+#else - static const struct pt_regs_offset x86_64_regoffset_table[] = { - REG_OFFSET_NAME_64("%ax", rax), - REG_OFFSET_NAME_64("%dx", rdx), -@@ -95,11 +99,7 @@ static const struct pt_regs_offset x86_64_regoffset_table[] = { - REG_OFFSET_END, - }; - --/* TODO: switching by dwarf address size */ --#ifdef __x86_64__ - #define regoffset_table x86_64_regoffset_table --#else --#define regoffset_table x86_32_regoffset_table - #endif - - /* Minus 1 for the ending REG_OFFSET_END */ -diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c -index 492df2752a2d..b4eb5b679081 100644 ---- a/tools/perf/bench/numa.c -+++ b/tools/perf/bench/numa.c -@@ -1570,13 +1570,13 @@ static int __bench_numa(const char *name) - "GB/sec,", "total-speed", "GB/sec total speed"); - - if (g->p.show_details >= 2) { -- char tname[32]; -+ char tname[14 + 2 * 10 + 1]; - struct thread_data *td; - for (p = 0; p < g->p.nr_proc; p++) { - for (t = 0; t < g->p.nr_threads; t++) { -- memset(tname, 0, 32); -+ memset(tname, 0, sizeof(tname)); - td = g->threads + p*g->p.nr_threads + t; -- snprintf(tname, 32, "process%d:thread%d", p, t); -+ snprintf(tname, sizeof(tname), "process%d:thread%d", p, t); - print_res(tname, td->speed_gbs, - "GB/sec", "thread-speed", "GB/sec/thread speed"); - print_res(tname, td->system_time_ns / 1e9, -diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c -index 72b5deb4bd79..20f0e27918dd 100644 ---- a/tools/perf/builtin-script.c -+++ b/tools/perf/builtin-script.c -@@ -1252,21 +1252,19 @@ static int is_directory(const char *base_path, const struct dirent *dent) - return S_ISDIR(st.st_mode); - } - --#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\ -- while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ -- lang_next) \ -- if ((lang_dirent.d_type == DT_DIR || \ -- (lang_dirent.d_type == DT_UNKNOWN && \ -- is_directory(scripts_path, &lang_dirent))) && \ -- (strcmp(lang_dirent.d_name, ".")) && \ -- (strcmp(lang_dirent.d_name, ".."))) -- --#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\ -- while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ -- script_next) \ -- if (script_dirent.d_type != DT_DIR && \ -- (script_dirent.d_type != DT_UNKNOWN || \ -- !is_directory(lang_path, &script_dirent))) -+#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \ -+ while ((lang_dirent = readdir(scripts_dir)) != NULL) \ -+ if ((lang_dirent->d_type == DT_DIR || \ -+ (lang_dirent->d_type == DT_UNKNOWN && \ -+ is_directory(scripts_path, lang_dirent))) && \ -+ (strcmp(lang_dirent->d_name, ".")) && \ -+ (strcmp(lang_dirent->d_name, ".."))) -+ -+#define for_each_script(lang_path, lang_dir, script_dirent) \ -+ while ((script_dirent = readdir(lang_dir)) != NULL) \ -+ if (script_dirent->d_type != DT_DIR && \ -+ (script_dirent->d_type != DT_UNKNOWN || \ -+ !is_directory(lang_path, script_dirent))) - - - #define RECORD_SUFFIX "-record" -@@ -1412,7 +1410,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused, - const char *s __maybe_unused, - int unset __maybe_unused) - { -- struct dirent *script_next, *lang_next, script_dirent, lang_dirent; -+ struct dirent *script_dirent, *lang_dirent; - char scripts_path[MAXPATHLEN]; - DIR *scripts_dir, *lang_dir; - char script_path[MAXPATHLEN]; -@@ -1427,19 +1425,19 @@ static int list_available_scripts(const struct option *opt __maybe_unused, - if (!scripts_dir) - return -1; - -- for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { -+ for_each_lang(scripts_path, scripts_dir, lang_dirent) { - snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, -- lang_dirent.d_name); -+ lang_dirent->d_name); - lang_dir = opendir(lang_path); - if (!lang_dir) - continue; - -- for_each_script(lang_path, lang_dir, script_dirent, script_next) { -- script_root = get_script_root(&script_dirent, REPORT_SUFFIX); -+ for_each_script(lang_path, lang_dir, script_dirent) { -+ script_root = get_script_root(script_dirent, REPORT_SUFFIX); - if (script_root) { - desc = script_desc__findnew(script_root); - snprintf(script_path, MAXPATHLEN, "%s/%s", -- lang_path, script_dirent.d_name); -+ lang_path, script_dirent->d_name); - read_script_info(desc, script_path); - free(script_root); - } -@@ -1527,7 +1525,7 @@ static int check_ev_match(char *dir_name, char *scriptname, - */ - int find_scripts(char **scripts_array, char **scripts_path_array) - { -- struct dirent *script_next, *lang_next, script_dirent, lang_dirent; -+ struct dirent *script_dirent, *lang_dirent; - char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; - DIR *scripts_dir, *lang_dir; - struct perf_session *session; -@@ -1550,9 +1548,9 @@ int find_scripts(char **scripts_array, char **scripts_path_array) - return -1; - } - -- for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { -+ for_each_lang(scripts_path, scripts_dir, lang_dirent) { - snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, -- lang_dirent.d_name); -+ lang_dirent->d_name); - #ifdef NO_LIBPERL - if (strstr(lang_path, "perl")) - continue; -@@ -1566,16 +1564,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array) - if (!lang_dir) - continue; - -- for_each_script(lang_path, lang_dir, script_dirent, script_next) { -+ for_each_script(lang_path, lang_dir, script_dirent) { - /* Skip those real time scripts: xxxtop.p[yl] */ -- if (strstr(script_dirent.d_name, "top.")) -+ if (strstr(script_dirent->d_name, "top.")) - continue; - sprintf(scripts_path_array[i], "%s/%s", lang_path, -- script_dirent.d_name); -- temp = strchr(script_dirent.d_name, '.'); -+ script_dirent->d_name); -+ temp = strchr(script_dirent->d_name, '.'); - snprintf(scripts_array[i], -- (temp - script_dirent.d_name) + 1, -- "%s", script_dirent.d_name); -+ (temp - script_dirent->d_name) + 1, -+ "%s", script_dirent->d_name); - - if (check_ev_match(lang_path, - scripts_array[i], session)) -@@ -1593,7 +1591,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array) - - static char *get_script_path(const char *script_root, const char *suffix) - { -- struct dirent *script_next, *lang_next, script_dirent, lang_dirent; -+ struct dirent *script_dirent, *lang_dirent; - char scripts_path[MAXPATHLEN]; - char script_path[MAXPATHLEN]; - DIR *scripts_dir, *lang_dir; -@@ -1606,21 +1604,21 @@ static char *get_script_path(const char *script_root, const char *suffix) - if (!scripts_dir) - return NULL; - -- for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { -+ for_each_lang(scripts_path, scripts_dir, lang_dirent) { - snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, -- lang_dirent.d_name); -+ lang_dirent->d_name); - lang_dir = opendir(lang_path); - if (!lang_dir) - continue; - -- for_each_script(lang_path, lang_dir, script_dirent, script_next) { -- __script_root = get_script_root(&script_dirent, suffix); -+ for_each_script(lang_path, lang_dir, script_dirent) { -+ __script_root = get_script_root(script_dirent, suffix); - if (__script_root && !strcmp(script_root, __script_root)) { - free(__script_root); - closedir(lang_dir); - closedir(scripts_dir); - snprintf(script_path, MAXPATHLEN, "%s/%s", -- lang_path, script_dirent.d_name); -+ lang_path, script_dirent->d_name); - return strdup(script_path); - } - free(__script_root); -diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c -index 7e2e72e6d9d1..4a8a02c302d2 100644 ---- a/tools/perf/builtin-top.c -+++ b/tools/perf/builtin-top.c -@@ -636,7 +636,7 @@ repeat: - case -1: - if (errno == EINTR) - continue; -- /* Fall trhu */ -+ __fallthrough; - default: - c = getc(stdin); - tcsetattr(0, TCSAFLUSH, &save); -diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c -index c783d8fd3a80..ebe7115c751a 100644 ---- a/tools/perf/builtin-trace.c -+++ b/tools/perf/builtin-trace.c -@@ -1617,6 +1617,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine, - color_fprintf(trace->output, PERF_COLOR_RED, - "LOST %" PRIu64 " events!\n", event->lost.lost); - ret = machine__process_lost_event(machine, event, sample); -+ break; - default: - ret = machine__process_event(machine, event, sample); - break; -diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c -index 636d7b42d844..54af2f2e2ee4 100644 ---- a/tools/perf/tests/parse-events.c -+++ b/tools/perf/tests/parse-events.c -@@ -1727,15 +1727,14 @@ static int test_pmu_events(void) - } - - while (!ret && (ent = readdir(dir))) { --#define MAX_NAME 100 - struct evlist_test e; -- char name[MAX_NAME]; -+ char name[2 * NAME_MAX + 1 + 12 + 3]; - - if (!strcmp(ent->d_name, ".") || - !strcmp(ent->d_name, "..")) - continue; - -- snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); -+ snprintf(name, sizeof(name), "cpu/event=%s/u", ent->d_name); - - e.name = name; - e.check = test__checkevent_pmu_events; -@@ -1743,11 +1742,10 @@ static int test_pmu_events(void) - ret = test_event(&e); - if (ret) - break; -- snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name); -+ snprintf(name, sizeof(name), "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name); - e.name = name; - e.check = test__checkevent_pmu_events_mix; - ret = test_event(&e); --#undef MAX_NAME - } - - closedir(dir); -diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c -index d4d7cc27252f..718bd46d47fa 100644 ---- a/tools/perf/ui/browsers/annotate.c -+++ b/tools/perf/ui/browsers/annotate.c -@@ -755,11 +755,11 @@ static int annotate_browser__run(struct annotate_browser *browser, - nd = browser->curr_hot; - break; - case K_UNTAB: -- if (nd != NULL) -+ if (nd != NULL) { - nd = rb_next(nd); - if (nd == NULL) - nd = rb_first(&browser->entries); -- else -+ } else - nd = browser->curr_hot; - break; - case K_F1: -diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c -index 956187bf1a85..26cba64345e3 100644 ---- a/tools/perf/util/event.c -+++ b/tools/perf/util/event.c -@@ -416,7 +416,7 @@ static int __event__synthesize_thread(union perf_event *comm_event, - { - char filename[PATH_MAX]; - DIR *tasks; -- struct dirent dirent, *next; -+ struct dirent *dirent; - pid_t tgid, ppid; - int rc = 0; - -@@ -445,11 +445,11 @@ static int __event__synthesize_thread(union perf_event *comm_event, - return 0; - } - -- while (!readdir_r(tasks, &dirent, &next) && next) { -+ while ((dirent = readdir(tasks)) != NULL) { - char *end; - pid_t _pid; - -- _pid = strtol(dirent.d_name, &end, 10); -+ _pid = strtol(dirent->d_name, &end, 10); - if (*end) - continue; - -@@ -558,7 +558,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, - { - DIR *proc; - char proc_path[PATH_MAX]; -- struct dirent dirent, *next; -+ struct dirent *dirent; - union perf_event *comm_event, *mmap_event, *fork_event; - int err = -1; - -@@ -583,9 +583,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool, - if (proc == NULL) - goto out_free_fork; - -- while (!readdir_r(proc, &dirent, &next) && next) { -+ while ((dirent = readdir(proc)) != NULL) { - char *end; -- pid_t pid = strtol(dirent.d_name, &end, 10); -+ pid_t pid = strtol(dirent->d_name, &end, 10); - - if (*end) /* only interested in proper numerical dirents */ - continue; -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -index 71df7acf8643..933a509a90f8 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include "../cache.h" - #include "../util.h" -@@ -1708,6 +1709,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) - switch (decoder->packet.type) { - case INTEL_PT_TIP_PGD: - decoder->continuous_period = false; -+ __fallthrough; - case INTEL_PT_TIP_PGE: - case INTEL_PT_TIP: - intel_pt_log("ERROR: Unexpected packet\n"); -@@ -1762,6 +1764,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) - decoder->pge = false; - decoder->continuous_period = false; - intel_pt_clear_tx_flags(decoder); -+ __fallthrough; -+ - case INTEL_PT_TNT: - decoder->have_tma = false; - intel_pt_log("ERROR: Unexpected packet\n"); -@@ -1802,6 +1806,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) - switch (decoder->packet.type) { - case INTEL_PT_TIP_PGD: - decoder->continuous_period = false; -+ __fallthrough; - case INTEL_PT_TIP_PGE: - case INTEL_PT_TIP: - decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -index b1257c816310..9b2fce25162b 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "intel-pt-pkt-decoder.h" - -@@ -488,6 +489,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, - case INTEL_PT_FUP: - if (!(packet->count)) - return snprintf(buf, buf_len, "%s no ip", name); -+ __fallthrough; - case INTEL_PT_CYC: - case INTEL_PT_VMCS: - case INTEL_PT_MTC: -diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c -index a35db828bd0d..38304b7e4f81 100644 ---- a/tools/perf/util/parse-events.c -+++ b/tools/perf/util/parse-events.c -@@ -138,11 +138,11 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { - #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) - #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) - --#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ -- while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ -- if (sys_dirent.d_type == DT_DIR && \ -- (strcmp(sys_dirent.d_name, ".")) && \ -- (strcmp(sys_dirent.d_name, ".."))) -+#define for_each_subsystem(sys_dir, sys_dirent) \ -+ while ((sys_dirent = readdir(sys_dir)) != NULL) \ -+ if (sys_dirent->d_type == DT_DIR && \ -+ (strcmp(sys_dirent->d_name, ".")) && \ -+ (strcmp(sys_dirent->d_name, ".."))) - - static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) - { -@@ -159,12 +159,12 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) - return 0; - } - --#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ -- while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ -- if (evt_dirent.d_type == DT_DIR && \ -- (strcmp(evt_dirent.d_name, ".")) && \ -- (strcmp(evt_dirent.d_name, "..")) && \ -- (!tp_event_has_id(&sys_dirent, &evt_dirent))) -+#define for_each_event(sys_dirent, evt_dir, evt_dirent) \ -+ while ((evt_dirent = readdir(evt_dir)) != NULL) \ -+ if (evt_dirent->d_type == DT_DIR && \ -+ (strcmp(evt_dirent->d_name, ".")) && \ -+ (strcmp(evt_dirent->d_name, "..")) && \ -+ (!tp_event_has_id(sys_dirent, evt_dirent))) - - #define MAX_EVENT_LENGTH 512 - -@@ -173,7 +173,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) - { - struct tracepoint_path *path = NULL; - DIR *sys_dir, *evt_dir; -- struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; -+ struct dirent *sys_dirent, *evt_dirent; - char id_buf[24]; - int fd; - u64 id; -@@ -184,18 +184,18 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) - if (!sys_dir) - return NULL; - -- for_each_subsystem(sys_dir, sys_dirent, sys_next) { -+ for_each_subsystem(sys_dir, sys_dirent) { - - snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, -- sys_dirent.d_name); -+ sys_dirent->d_name); - evt_dir = opendir(dir_path); - if (!evt_dir) - continue; - -- for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { -+ for_each_event(sys_dirent, evt_dir, evt_dirent) { - - snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, -- evt_dirent.d_name); -+ evt_dirent->d_name); - fd = open(evt_path, O_RDONLY); - if (fd < 0) - continue; -@@ -220,9 +220,9 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) - free(path); - return NULL; - } -- strncpy(path->system, sys_dirent.d_name, -+ strncpy(path->system, sys_dirent->d_name, - MAX_EVENT_LENGTH); -- strncpy(path->name, evt_dirent.d_name, -+ strncpy(path->name, evt_dirent->d_name, - MAX_EVENT_LENGTH); - return path; - } -@@ -1629,7 +1629,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, - bool name_only) - { - DIR *sys_dir, *evt_dir; -- struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; -+ struct dirent *sys_dirent, *evt_dirent; - char evt_path[MAXPATHLEN]; - char dir_path[MAXPATHLEN]; - char **evt_list = NULL; -@@ -1647,20 +1647,20 @@ restart: - goto out_close_sys_dir; - } - -- for_each_subsystem(sys_dir, sys_dirent, sys_next) { -+ for_each_subsystem(sys_dir, sys_dirent) { - if (subsys_glob != NULL && -- !strglobmatch(sys_dirent.d_name, subsys_glob)) -+ !strglobmatch(sys_dirent->d_name, subsys_glob)) - continue; - - snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, -- sys_dirent.d_name); -+ sys_dirent->d_name); - evt_dir = opendir(dir_path); - if (!evt_dir) - continue; - -- for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { -+ for_each_event(sys_dirent, evt_dir, evt_dirent) { - if (event_glob != NULL && -- !strglobmatch(evt_dirent.d_name, event_glob)) -+ !strglobmatch(evt_dirent->d_name, event_glob)) - continue; - - if (!evt_num_known) { -@@ -1669,7 +1669,7 @@ restart: - } - - snprintf(evt_path, MAXPATHLEN, "%s:%s", -- sys_dirent.d_name, evt_dirent.d_name); -+ sys_dirent->d_name, evt_dirent->d_name); - - evt_list[evt_i] = strdup(evt_path); - if (evt_list[evt_i] == NULL) -@@ -1722,7 +1722,7 @@ out_close_sys_dir: - int is_valid_tracepoint(const char *event_string) - { - DIR *sys_dir, *evt_dir; -- struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; -+ struct dirent *sys_dirent, *evt_dirent; - char evt_path[MAXPATHLEN]; - char dir_path[MAXPATHLEN]; - -@@ -1730,17 +1730,17 @@ int is_valid_tracepoint(const char *event_string) - if (!sys_dir) - return 0; - -- for_each_subsystem(sys_dir, sys_dirent, sys_next) { -+ for_each_subsystem(sys_dir, sys_dirent) { - - snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, -- sys_dirent.d_name); -+ sys_dirent->d_name); - evt_dir = opendir(dir_path); - if (!evt_dir) - continue; - -- for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { -+ for_each_event(sys_dirent, evt_dir, evt_dirent) { - snprintf(evt_path, MAXPATHLEN, "%s:%s", -- sys_dirent.d_name, evt_dirent.d_name); -+ sys_dirent->d_name, evt_dirent->d_name); - if (!strcmp(evt_path, event_string)) { - closedir(evt_dir); - closedir(sys_dir); -diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c -index 6f2a0279476c..593066c68e3d 100644 ---- a/tools/perf/util/pmu.c -+++ b/tools/perf/util/pmu.c -@@ -153,7 +153,7 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *n - if (fd == -1) - return -1; - -- sret = read(fd, alias->unit, UNIT_MAX_LEN); -+ sret = read(fd, alias->unit, UNIT_MAX_LEN); - if (sret < 0) - goto error; - -diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build -index 6516e220c247..82d28c67e0f3 100644 ---- a/tools/perf/util/scripting-engines/Build -+++ b/tools/perf/util/scripting-engines/Build -@@ -1,6 +1,6 @@ - libperf-$(CONFIG_LIBPERL) += trace-event-perl.o - libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o - --CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default -+CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-nested-externs -Wno-undef -Wno-switch-default - - CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c -index bcae659b6546..efb53772e0ec 100644 ---- a/tools/perf/util/strfilter.c -+++ b/tools/perf/util/strfilter.c -@@ -269,6 +269,7 @@ static int strfilter_node__sprint(struct strfilter_node *node, char *buf) - len = strfilter_node__sprint_pt(node->l, buf); - if (len < 0) - return len; -+ __fallthrough; - case '!': - if (buf) { - *(buf + len++) = *node->p; -diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c -index fc8781de62db..accb7ece1d3c 100644 ---- a/tools/perf/util/string.c -+++ b/tools/perf/util/string.c -@@ -21,6 +21,8 @@ s64 perf_atoll(const char *str) - case 'b': case 'B': - if (*p) - goto out_err; -+ -+ __fallthrough; - case '\0': - return length; - default: -diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c -index 0a9ae8014729..829508a21448 100644 ---- a/tools/perf/util/thread.c -+++ b/tools/perf/util/thread.c -@@ -227,7 +227,7 @@ void thread__find_cpumode_addr_location(struct thread *thread, - struct addr_location *al) - { - size_t i; -- const u8 const cpumodes[] = { -+ const u8 cpumodes[] = { - PERF_RECORD_MISC_USER, - PERF_RECORD_MISC_KERNEL, - PERF_RECORD_MISC_GUEST_USER, -diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c -index 6ec3c5ca438f..4e666b95b87e 100644 ---- a/tools/perf/util/thread_map.c -+++ b/tools/perf/util/thread_map.c -@@ -92,8 +92,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) - { - DIR *proc; - int max_threads = 32, items, i; -- char path[256]; -- struct dirent dirent, *next, **namelist = NULL; -+ char path[NAME_MAX + 1 + 6]; -+ struct dirent *dirent, **namelist = NULL; - struct thread_map *threads = thread_map__alloc(max_threads); - - if (threads == NULL) -@@ -106,16 +106,16 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) - threads->nr = 0; - atomic_set(&threads->refcnt, 1); - -- while (!readdir_r(proc, &dirent, &next) && next) { -+ while ((dirent = readdir(proc)) != NULL) { - char *end; - bool grow = false; - struct stat st; -- pid_t pid = strtol(dirent.d_name, &end, 10); -+ pid_t pid = strtol(dirent->d_name, &end, 10); - - if (*end) /* only interested in proper numerical dirents */ - continue; - -- snprintf(path, sizeof(path), "/proc/%s", dirent.d_name); -+ snprintf(path, sizeof(path), "/proc/%s", dirent->d_name); - - if (stat(path, &st) != 0) - continue; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.77-78.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.77-78.patch deleted file mode 100644 index 7bbeb8ee6..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.77-78.patch +++ /dev/null @@ -1,3019 +0,0 @@ -diff --git a/Makefile b/Makefile -index bf49a61d02e2..ac77ae8ee0b1 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 77 -+SUBLEVEL = 78 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h -index d2315ffd8f12..f13ae153fb24 100644 ---- a/arch/arm/include/asm/elf.h -+++ b/arch/arm/include/asm/elf.h -@@ -112,12 +112,8 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); - #define CORE_DUMP_USE_REGSET - #define ELF_EXEC_PAGESIZE 4096 - --/* This is the location that an ET_DYN program is loaded if exec'ed. Typical -- use of this is to invoke "./ld.so someprog" to test out a new version of -- the loader. We need to make sure that it is out of the way of the program -- that it will "exec", and that there is sufficient room for the brk. */ -- --#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) -+/* This is the base location for PIE (ET_DYN with INTERP) loads. */ -+#define ELF_ET_DYN_BASE 0x400000UL - - /* When the program starts, a1 contains a pointer to a function to be - registered with atexit, as per the SVR4 ABI. A value of 0 means we -diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h -index 44dd892a4bbe..9e11dbe1cec3 100644 ---- a/arch/arm64/include/asm/elf.h -+++ b/arch/arm64/include/asm/elf.h -@@ -120,12 +120,11 @@ typedef struct user_fpsimd_state elf_fpregset_t; - #define ELF_EXEC_PAGESIZE PAGE_SIZE - - /* -- * This is the location that an ET_DYN program is loaded if exec'ed. Typical -- * use of this is to invoke "./ld.so someprog" to test out a new version of -- * the loader. We need to make sure that it is out of the way of the program -- * that it will "exec", and that there is sufficient room for the brk. -+ * This is the base location for PIE (ET_DYN with INTERP) loads. On -+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * space open for things that want to use the area for 32-bit pointers. - */ --#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3) -+#define ELF_ET_DYN_BASE 0x100000000UL - - /* - * When the program starts, a1 contains a pointer to a function to be -@@ -165,7 +164,8 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, - - #ifdef CONFIG_COMPAT - --#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3) -+/* PIE load location for compat arm. Must match ARM ELF_ET_DYN_BASE. */ -+#define COMPAT_ELF_ET_DYN_BASE 0x000400000UL - - /* AArch32 registers. */ - #define COMPAT_ELF_NGREG 18 -diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h -index d8d60a57183f..f53725202955 100644 ---- a/arch/parisc/include/asm/dma-mapping.h -+++ b/arch/parisc/include/asm/dma-mapping.h -@@ -39,6 +39,8 @@ struct hppa_dma_ops { - ** flush/purge and allocate "regular" cacheable pages for everything. - */ - -+#define DMA_ERROR_CODE (~(dma_addr_t)0) -+ - #ifdef CONFIG_PA11 - extern struct hppa_dma_ops pcxl_dma_ops; - extern struct hppa_dma_ops pcx_dma_ops; -@@ -209,12 +211,13 @@ parisc_walk_tree(struct device *dev) - break; - } - } -- BUG_ON(!dev->platform_data); - return dev->platform_data; - } -- --#define GET_IOC(dev) (HBA_DATA(parisc_walk_tree(dev))->iommu) -- -+ -+#define GET_IOC(dev) ({ \ -+ void *__pdata = parisc_walk_tree(dev); \ -+ __pdata ? HBA_DATA(__pdata)->iommu : NULL; \ -+}) - - #ifdef CONFIG_IOMMU_CCIO - struct parisc_device; -diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h -index 59be25764433..a81226257878 100644 ---- a/arch/parisc/include/asm/mmu_context.h -+++ b/arch/parisc/include/asm/mmu_context.h -@@ -49,15 +49,26 @@ static inline void load_context(mm_context_t context) - mtctl(__space_to_prot(context), 8); - } - --static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) -+static inline void switch_mm_irqs_off(struct mm_struct *prev, -+ struct mm_struct *next, struct task_struct *tsk) - { -- - if (prev != next) { - mtctl(__pa(next->pgd), 25); - load_context(next->context); - } - } - -+static inline void switch_mm(struct mm_struct *prev, -+ struct mm_struct *next, struct task_struct *tsk) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ switch_mm_irqs_off(prev, next, tsk); -+ local_irq_restore(flags); -+} -+#define switch_mm_irqs_off switch_mm_irqs_off -+ - #define deactivate_mm(tsk,mm) do { } while (0) - - static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) -diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S -index d4ffcfbc9885..041e1f9ec129 100644 ---- a/arch/parisc/kernel/syscall_table.S -+++ b/arch/parisc/kernel/syscall_table.S -@@ -361,7 +361,7 @@ - ENTRY_SAME(ni_syscall) /* 263: reserved for vserver */ - ENTRY_SAME(add_key) - ENTRY_SAME(request_key) /* 265 */ -- ENTRY_SAME(keyctl) -+ ENTRY_COMP(keyctl) - ENTRY_SAME(ioprio_set) - ENTRY_SAME(ioprio_get) - ENTRY_SAME(inotify_init) -diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c -index f9064449908a..d8c2f3bcfc18 100644 ---- a/arch/parisc/mm/fault.c -+++ b/arch/parisc/mm/fault.c -@@ -303,7 +303,7 @@ bad_area: - case 15: /* Data TLB miss fault/Data page fault */ - /* send SIGSEGV when outside of vma */ - if (!vma || -- address < vma->vm_start || address > vma->vm_end) { -+ address < vma->vm_start || address >= vma->vm_end) { - si.si_signo = SIGSEGV; - si.si_code = SEGV_MAPERR; - break; -diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h -index ee46ffef608e..743ad7a400d6 100644 ---- a/arch/powerpc/include/asm/elf.h -+++ b/arch/powerpc/include/asm/elf.h -@@ -23,12 +23,13 @@ - #define CORE_DUMP_USE_REGSET - #define ELF_EXEC_PAGESIZE PAGE_SIZE - --/* This is the location that an ET_DYN program is loaded if exec'ed. Typical -- use of this is to invoke "./ld.so someprog" to test out a new version of -- the loader. We need to make sure that it is out of the way of the program -- that it will "exec", and that there is sufficient room for the brk. */ -- --#define ELF_ET_DYN_BASE 0x20000000 -+/* -+ * This is the base location for PIE (ET_DYN with INTERP) loads. On -+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * space open for things that want to use the area for 32-bit pointers. -+ */ -+#define ELF_ET_DYN_BASE (is_32bit_task() ? 0x000400000UL : \ -+ 0x100000000UL) - - #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0) - -diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h -index bab6739a1154..b9eb7b1a49d2 100644 ---- a/arch/s390/include/asm/elf.h -+++ b/arch/s390/include/asm/elf.h -@@ -154,14 +154,13 @@ extern unsigned int vdso_enabled; - #define CORE_DUMP_USE_REGSET - #define ELF_EXEC_PAGESIZE 4096 - --/* This is the location that an ET_DYN program is loaded if exec'ed. Typical -- use of this is to invoke "./ld.so someprog" to test out a new version of -- the loader. We need to make sure that it is out of the way of the program -- that it will "exec", and that there is sufficient room for the brk. 64-bit -- tasks are aligned to 4GB. */ --#define ELF_ET_DYN_BASE (is_32bit_task() ? \ -- (STACK_TOP / 3 * 2) : \ -- (STACK_TOP / 3 * 2) & ~((1UL << 32) - 1)) -+/* -+ * This is the base location for PIE (ET_DYN with INTERP) loads. On -+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * space open for things that want to use the area for 32-bit pointers. -+ */ -+#define ELF_ET_DYN_BASE (is_compat_task() ? 0x000400000UL : \ -+ 0x100000000UL) - - /* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. */ -diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c -index dd14616b7739..7de207a11014 100644 ---- a/arch/x86/crypto/sha1_ssse3_glue.c -+++ b/arch/x86/crypto/sha1_ssse3_glue.c -@@ -201,7 +201,7 @@ asmlinkage void sha1_transform_avx2(u32 *digest, const char *data, - - static bool avx2_usable(void) - { -- if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) -+ if (false && avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) - && boot_cpu_has(X86_FEATURE_BMI1) - && boot_cpu_has(X86_FEATURE_BMI2)) - return true; -diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h -index d262f985bbc8..07cf288b692e 100644 ---- a/arch/x86/include/asm/elf.h -+++ b/arch/x86/include/asm/elf.h -@@ -245,12 +245,13 @@ extern int force_personality32; - #define CORE_DUMP_USE_REGSET - #define ELF_EXEC_PAGESIZE 4096 - --/* This is the location that an ET_DYN program is loaded if exec'ed. Typical -- use of this is to invoke "./ld.so someprog" to test out a new version of -- the loader. We need to make sure that it is out of the way of the program -- that it will "exec", and that there is sufficient room for the brk. */ -- --#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) -+/* -+ * This is the base location for PIE (ET_DYN with INTERP) loads. On -+ * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * space open for things that want to use the area for 32-bit pointers. -+ */ -+#define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \ -+ 0x100000000UL) - - /* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. This could be done in user space, -diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h -index 690b4027e17c..37db36fddc88 100644 ---- a/arch/x86/include/asm/msr-index.h -+++ b/arch/x86/include/asm/msr-index.h -@@ -405,6 +405,8 @@ - #define MSR_IA32_TSC_ADJUST 0x0000003b - #define MSR_IA32_BNDCFGS 0x00000d90 - -+#define MSR_IA32_BNDCFGS_RSVD 0x00000ffc -+ - #define MSR_IA32_XSS 0x00000da0 - - #define FEATURE_CONTROL_LOCKED (1<<0) -diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c -index 9357b29de9bc..83d6369c45f5 100644 ---- a/arch/x86/kvm/cpuid.c -+++ b/arch/x86/kvm/cpuid.c -@@ -46,11 +46,18 @@ static u32 xstate_required_size(u64 xstate_bv, bool compacted) - return ret; - } - -+bool kvm_mpx_supported(void) -+{ -+ return ((host_xcr0 & (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR)) -+ && kvm_x86_ops->mpx_supported()); -+} -+EXPORT_SYMBOL_GPL(kvm_mpx_supported); -+ - u64 kvm_supported_xcr0(void) - { - u64 xcr0 = KVM_SUPPORTED_XCR0 & host_xcr0; - -- if (!kvm_x86_ops->mpx_supported()) -+ if (!kvm_mpx_supported()) - xcr0 &= ~(XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR); - - return xcr0; -@@ -97,7 +104,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu) - if (best && (best->eax & (F(XSAVES) | F(XSAVEC)))) - best->ebx = xstate_required_size(vcpu->arch.xcr0, true); - -- vcpu->arch.eager_fpu = use_eager_fpu() || guest_cpuid_has_mpx(vcpu); -+ vcpu->arch.eager_fpu = use_eager_fpu(); - if (vcpu->arch.eager_fpu) - kvm_x86_ops->fpu_activate(vcpu); - -@@ -295,7 +302,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, - #endif - unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0; - unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0; -- unsigned f_mpx = kvm_x86_ops->mpx_supported() ? F(MPX) : 0; -+ unsigned f_mpx = kvm_mpx_supported() ? F(MPX) : 0; - unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0; - - /* cpuid 1.edx */ -diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h -index 3f5c48ddba45..d1534feefcfe 100644 ---- a/arch/x86/kvm/cpuid.h -+++ b/arch/x86/kvm/cpuid.h -@@ -4,6 +4,7 @@ - #include "x86.h" - - int kvm_update_cpuid(struct kvm_vcpu *vcpu); -+bool kvm_mpx_supported(void); - struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, - u32 function, u32 index); - int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, -@@ -134,20 +135,20 @@ static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu) - return best && (best->ebx & bit(X86_FEATURE_RTM)); - } - --static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) -+static inline bool guest_cpuid_has_pcommit(struct kvm_vcpu *vcpu) - { - struct kvm_cpuid_entry2 *best; - - best = kvm_find_cpuid_entry(vcpu, 7, 0); -- return best && (best->ebx & bit(X86_FEATURE_MPX)); -+ return best && (best->ebx & bit(X86_FEATURE_PCOMMIT)); - } - --static inline bool guest_cpuid_has_pcommit(struct kvm_vcpu *vcpu) -+static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) - { - struct kvm_cpuid_entry2 *best; - - best = kvm_find_cpuid_entry(vcpu, 7, 0); -- return best && (best->ebx & bit(X86_FEATURE_PCOMMIT)); -+ return best && (best->ebx & bit(X86_FEATURE_MPX)); - } - - static inline bool guest_cpuid_has_rdtscp(struct kvm_vcpu *vcpu) -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index bbaa11f4e74b..b12391119ce8 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -863,7 +863,6 @@ static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu); - static u64 construct_eptp(unsigned long root_hpa); - static void kvm_cpu_vmxon(u64 addr); - static void kvm_cpu_vmxoff(void); --static bool vmx_mpx_supported(void); - static bool vmx_xsaves_supported(void); - static int vmx_cpu_uses_apicv(struct kvm_vcpu *vcpu); - static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr); -@@ -2541,7 +2540,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) - VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER | - VM_EXIT_SAVE_VMX_PREEMPTION_TIMER | VM_EXIT_ACK_INTR_ON_EXIT; - -- if (vmx_mpx_supported()) -+ if (kvm_mpx_supported()) - vmx->nested.nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS; - - /* We support free control of debug control saving. */ -@@ -2562,7 +2561,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx) - VM_ENTRY_LOAD_IA32_PAT; - vmx->nested.nested_vmx_entry_ctls_high |= - (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER); -- if (vmx_mpx_supported()) -+ if (kvm_mpx_supported()) - vmx->nested.nested_vmx_entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS; - - /* We support free control of debug control loading. */ -@@ -2813,7 +2812,8 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP); - break; - case MSR_IA32_BNDCFGS: -- if (!vmx_mpx_supported()) -+ if (!kvm_mpx_supported() || -+ (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu))) - return 1; - msr_info->data = vmcs_read64(GUEST_BNDCFGS); - break; -@@ -2890,7 +2890,11 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) - vmcs_writel(GUEST_SYSENTER_ESP, data); - break; - case MSR_IA32_BNDCFGS: -- if (!vmx_mpx_supported()) -+ if (!kvm_mpx_supported() || -+ (!msr_info->host_initiated && !guest_cpuid_has_mpx(vcpu))) -+ return 1; -+ if (is_noncanonical_address(data & PAGE_MASK) || -+ (data & MSR_IA32_BNDCFGS_RSVD)) - return 1; - vmcs_write64(GUEST_BNDCFGS, data); - break; -@@ -3363,7 +3367,7 @@ static void init_vmcs_shadow_fields(void) - for (i = j = 0; i < max_shadow_read_write_fields; i++) { - switch (shadow_read_write_fields[i]) { - case GUEST_BNDCFGS: -- if (!vmx_mpx_supported()) -+ if (!kvm_mpx_supported()) - continue; - break; - default: -@@ -6253,7 +6257,6 @@ static __init int hardware_setup(void) - vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); - vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); - vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); -- vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); - - memcpy(vmx_msr_bitmap_legacy_x2apic, - vmx_msr_bitmap_legacy, PAGE_SIZE); -@@ -10265,7 +10268,7 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, - vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS); - vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP); - vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP); -- if (vmx_mpx_supported()) -+ if (kvm_mpx_supported()) - vmcs12->guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS); - if (nested_cpu_has_xsaves(vmcs12)) - vmcs12->xss_exit_bitmap = vmcs_read64(XSS_EXIT_BITMAP); -diff --git a/drivers/base/core.c b/drivers/base/core.c -index f18856f5954b..afe045792796 100644 ---- a/drivers/base/core.c -+++ b/drivers/base/core.c -@@ -2094,7 +2094,11 @@ void device_shutdown(void) - pm_runtime_get_noresume(dev); - pm_runtime_barrier(dev); - -- if (dev->bus && dev->bus->shutdown) { -+ if (dev->class && dev->class->shutdown) { -+ if (initcall_debug) -+ dev_info(dev, "shutdown\n"); -+ dev->class->shutdown(dev); -+ } else if (dev->bus && dev->bus->shutdown) { - if (initcall_debug) - dev_info(dev, "shutdown\n"); - dev->bus->shutdown(dev); -diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c -index a7b46798c81d..39efa7e6c0c0 100644 ---- a/drivers/base/power/sysfs.c -+++ b/drivers/base/power/sysfs.c -@@ -268,6 +268,8 @@ static ssize_t pm_qos_latency_tolerance_store(struct device *dev, - value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; - else if (!strcmp(buf, "any") || !strcmp(buf, "any\n")) - value = PM_QOS_LATENCY_ANY; -+ else -+ return -EINVAL; - } - ret = dev_pm_qos_update_user_latency_tolerance(dev, value); - return ret < 0 ? ret : n; -diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c -index a1e0b9ab847a..e613633ffe9c 100644 ---- a/drivers/base/power/wakeup.c -+++ b/drivers/base/power/wakeup.c -@@ -60,6 +60,8 @@ static LIST_HEAD(wakeup_sources); - - static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue); - -+DEFINE_STATIC_SRCU(wakeup_srcu); -+ - static struct wakeup_source deleted_ws = { - .name = "deleted", - .lock = __SPIN_LOCK_UNLOCKED(deleted_ws.lock), -@@ -198,7 +200,7 @@ void wakeup_source_remove(struct wakeup_source *ws) - spin_lock_irqsave(&events_lock, flags); - list_del_rcu(&ws->entry); - spin_unlock_irqrestore(&events_lock, flags); -- synchronize_rcu(); -+ synchronize_srcu(&wakeup_srcu); - } - EXPORT_SYMBOL_GPL(wakeup_source_remove); - -@@ -330,13 +332,14 @@ void device_wakeup_detach_irq(struct device *dev) - void device_wakeup_arm_wake_irqs(void) - { - struct wakeup_source *ws; -+ int srcuidx; - -- rcu_read_lock(); -+ srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { - if (ws->wakeirq) - dev_pm_arm_wake_irq(ws->wakeirq); - } -- rcu_read_unlock(); -+ srcu_read_unlock(&wakeup_srcu, srcuidx); - } - - /** -@@ -347,13 +350,14 @@ void device_wakeup_arm_wake_irqs(void) - void device_wakeup_disarm_wake_irqs(void) - { - struct wakeup_source *ws; -+ int srcuidx; - -- rcu_read_lock(); -+ srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { - if (ws->wakeirq) - dev_pm_disarm_wake_irq(ws->wakeirq); - } -- rcu_read_unlock(); -+ srcu_read_unlock(&wakeup_srcu, srcuidx); - } - - /** -@@ -807,10 +811,10 @@ EXPORT_SYMBOL_GPL(pm_wakeup_event); - void pm_print_active_wakeup_sources(void) - { - struct wakeup_source *ws; -- int active = 0; -+ int srcuidx, active = 0; - struct wakeup_source *last_activity_ws = NULL; - -- rcu_read_lock(); -+ srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { - if (ws->active) { - pr_info("active wakeup source: %s\n", ws->name); -@@ -826,7 +830,7 @@ void pm_print_active_wakeup_sources(void) - if (!active && last_activity_ws) - pr_info("last active wakeup source: %s\n", - last_activity_ws->name); -- rcu_read_unlock(); -+ srcu_read_unlock(&wakeup_srcu, srcuidx); - } - EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources); - -@@ -953,8 +957,9 @@ void pm_wakep_autosleep_enabled(bool set) - { - struct wakeup_source *ws; - ktime_t now = ktime_get(); -+ int srcuidx; - -- rcu_read_lock(); -+ srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) { - spin_lock_irq(&ws->lock); - if (ws->autosleep_enabled != set) { -@@ -968,7 +973,7 @@ void pm_wakep_autosleep_enabled(bool set) - } - spin_unlock_irq(&ws->lock); - } -- rcu_read_unlock(); -+ srcu_read_unlock(&wakeup_srcu, srcuidx); - } - #endif /* CONFIG_PM_AUTOSLEEP */ - -@@ -1029,15 +1034,16 @@ static int print_wakeup_source_stats(struct seq_file *m, - static int wakeup_sources_stats_show(struct seq_file *m, void *unused) - { - struct wakeup_source *ws; -+ int srcuidx; - - seq_puts(m, "name\t\tactive_count\tevent_count\twakeup_count\t" - "expire_count\tactive_since\ttotal_time\tmax_time\t" - "last_change\tprevent_suspend_time\n"); - -- rcu_read_lock(); -+ srcuidx = srcu_read_lock(&wakeup_srcu); - list_for_each_entry_rcu(ws, &wakeup_sources, entry) - print_wakeup_source_stats(m, ws); -- rcu_read_unlock(); -+ srcu_read_unlock(&wakeup_srcu, srcuidx); - - print_wakeup_source_stats(m, &deleted_ws); - -diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c -index 252142524ff2..6d56877b2e0a 100644 ---- a/drivers/char/tpm/tpm-chip.c -+++ b/drivers/char/tpm/tpm-chip.c -@@ -36,10 +36,60 @@ static DEFINE_SPINLOCK(driver_lock); - struct class *tpm_class; - dev_t tpm_devt; - --/* -- * tpm_chip_find_get - return tpm_chip for a given chip number -- * @chip_num the device number for the chip -+/** -+ * tpm_try_get_ops() - Get a ref to the tpm_chip -+ * @chip: Chip to ref -+ * -+ * The caller must already have some kind of locking to ensure that chip is -+ * valid. This function will lock the chip so that the ops member can be -+ * accessed safely. The locking prevents tpm_chip_unregister from -+ * completing, so it should not be held for long periods. -+ * -+ * Returns -ERRNO if the chip could not be got. -+ */ -+int tpm_try_get_ops(struct tpm_chip *chip) -+{ -+ int rc = -EIO; -+ -+ get_device(&chip->dev); -+ -+ down_read(&chip->ops_sem); -+ if (!chip->ops) -+ goto out_lock; -+ -+ if (!try_module_get(chip->dev.parent->driver->owner)) -+ goto out_lock; -+ -+ return 0; -+out_lock: -+ up_read(&chip->ops_sem); -+ put_device(&chip->dev); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(tpm_try_get_ops); -+ -+/** -+ * tpm_put_ops() - Release a ref to the tpm_chip -+ * @chip: Chip to put -+ * -+ * This is the opposite pair to tpm_try_get_ops(). After this returns chip may -+ * be kfree'd. - */ -+void tpm_put_ops(struct tpm_chip *chip) -+{ -+ module_put(chip->dev.parent->driver->owner); -+ up_read(&chip->ops_sem); -+ put_device(&chip->dev); -+} -+EXPORT_SYMBOL_GPL(tpm_put_ops); -+ -+/** -+ * tpm_chip_find_get() - return tpm_chip for a given chip number -+ * @chip_num: id to find -+ * -+ * The return'd chip has been tpm_try_get_ops'd and must be released via -+ * tpm_put_ops -+ */ - struct tpm_chip *tpm_chip_find_get(int chip_num) - { - struct tpm_chip *pos, *chip = NULL; -@@ -49,10 +99,10 @@ struct tpm_chip *tpm_chip_find_get(int chip_num) - if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) - continue; - -- if (try_module_get(pos->pdev->driver->owner)) { -+ /* rcu prevents chip from being free'd */ -+ if (!tpm_try_get_ops(pos)) - chip = pos; -- break; -- } -+ break; - } - rcu_read_unlock(); - return chip; -@@ -74,6 +124,41 @@ static void tpm_dev_release(struct device *dev) - kfree(chip); - } - -+ -+/** -+ * tpm_class_shutdown() - prepare the TPM device for loss of power. -+ * @dev: device to which the chip is associated. -+ * -+ * Issues a TPM2_Shutdown command prior to loss of power, as required by the -+ * TPM 2.0 spec. -+ * Then, calls bus- and device- specific shutdown code. -+ * -+ * XXX: This codepath relies on the fact that sysfs is not enabled for -+ * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2 -+ * has sysfs support enabled before TPM sysfs's implicit locking is fixed. -+ */ -+static int tpm_class_shutdown(struct device *dev) -+{ -+ struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); -+ -+ if (chip->flags & TPM_CHIP_FLAG_TPM2) { -+ down_write(&chip->ops_sem); -+ tpm2_shutdown(chip, TPM2_SU_CLEAR); -+ chip->ops = NULL; -+ up_write(&chip->ops_sem); -+ } -+ /* Allow bus- and device-specific code to run. Note: since chip->ops -+ * is NULL, more-specific shutdown code will not be able to issue TPM -+ * commands. -+ */ -+ if (dev->bus && dev->bus->shutdown) -+ dev->bus->shutdown(dev); -+ else if (dev->driver && dev->driver->shutdown) -+ dev->driver->shutdown(dev); -+ return 0; -+} -+ -+ - /** - * tpmm_chip_alloc() - allocate a new struct tpm_chip instance - * @dev: device to which the chip is associated -@@ -94,6 +179,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, - return ERR_PTR(-ENOMEM); - - mutex_init(&chip->tpm_mutex); -+ init_rwsem(&chip->ops_sem); - INIT_LIST_HEAD(&chip->list); - - chip->ops = ops; -@@ -112,13 +198,12 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, - - scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); - -- chip->pdev = dev; -- - dev_set_drvdata(dev, chip); - - chip->dev.class = tpm_class; -+ chip->dev.class->shutdown = tpm_class_shutdown; - chip->dev.release = tpm_dev_release; -- chip->dev.parent = chip->pdev; -+ chip->dev.parent = dev; - #ifdef CONFIG_ACPI - chip->dev.groups = chip->groups; - #endif -@@ -133,7 +218,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, - device_initialize(&chip->dev); - - cdev_init(&chip->cdev, &tpm_fops); -- chip->cdev.owner = chip->pdev->driver->owner; -+ chip->cdev.owner = dev->driver->owner; - chip->cdev.kobj.parent = &chip->dev.kobj; - - devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); -@@ -173,6 +258,12 @@ static int tpm_add_char_device(struct tpm_chip *chip) - static void tpm_del_char_device(struct tpm_chip *chip) - { - cdev_del(&chip->cdev); -+ -+ /* Make the driver uncallable. */ -+ down_write(&chip->ops_sem); -+ chip->ops = NULL; -+ up_write(&chip->ops_sem); -+ - device_del(&chip->dev); - } - -@@ -236,9 +327,8 @@ int tpm_chip_register(struct tpm_chip *chip) - chip->flags |= TPM_CHIP_FLAG_REGISTERED; - - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { -- rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj, -- &chip->dev.kobj, -- "ppi"); -+ rc = __compat_only_sysfs_link_entry_to_kobj( -+ &chip->dev.parent->kobj, &chip->dev.kobj, "ppi"); - if (rc && rc != -ENOENT) { - tpm_chip_unregister(chip); - return rc; -@@ -259,6 +349,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); - * Takes the chip first away from the list of available TPM chips and then - * cleans up all the resources reserved by tpm_chip_register(). - * -+ * Once this function returns the driver call backs in 'op's will not be -+ * running and will no longer start. -+ * - * NOTE: This function should be only called before deinitializing chip - * resources. - */ -@@ -273,7 +366,7 @@ void tpm_chip_unregister(struct tpm_chip *chip) - synchronize_rcu(); - - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) -- sysfs_remove_link(&chip->pdev->kobj, "ppi"); -+ sysfs_remove_link(&chip->dev.parent->kobj, "ppi"); - - tpm1_chip_unregister(chip); - tpm_del_char_device(chip); -diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c -index 4f3137d9a35e..912ad30be585 100644 ---- a/drivers/char/tpm/tpm-dev.c -+++ b/drivers/char/tpm/tpm-dev.c -@@ -61,7 +61,7 @@ static int tpm_open(struct inode *inode, struct file *file) - * by the check of is_open variable, which is protected - * by driver_lock. */ - if (test_and_set_bit(0, &chip->is_open)) { -- dev_dbg(chip->pdev, "Another process owns this TPM\n"); -+ dev_dbg(&chip->dev, "Another process owns this TPM\n"); - return -EBUSY; - } - -@@ -79,7 +79,6 @@ static int tpm_open(struct inode *inode, struct file *file) - INIT_WORK(&priv->work, timeout_work); - - file->private_data = priv; -- get_device(chip->pdev); - return 0; - } - -@@ -137,9 +136,18 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, - return -EFAULT; - } - -- /* atomic tpm command send and result receive */ -+ /* atomic tpm command send and result receive. We only hold the ops -+ * lock during this period so that the tpm can be unregistered even if -+ * the char dev is held open. -+ */ -+ if (tpm_try_get_ops(priv->chip)) { -+ mutex_unlock(&priv->buffer_mutex); -+ return -EPIPE; -+ } - out_size = tpm_transmit(priv->chip, priv->data_buffer, - sizeof(priv->data_buffer), 0); -+ -+ tpm_put_ops(priv->chip); - if (out_size < 0) { - mutex_unlock(&priv->buffer_mutex); - return out_size; -@@ -166,7 +174,6 @@ static int tpm_release(struct inode *inode, struct file *file) - file->private_data = NULL; - atomic_set(&priv->data_pending, 0); - clear_bit(0, &priv->chip->is_open); -- put_device(priv->chip->pdev); - kfree(priv); - return 0; - } -diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c -index 17abe52e6365..8588f2e4b9af 100644 ---- a/drivers/char/tpm/tpm-interface.c -+++ b/drivers/char/tpm/tpm-interface.c -@@ -343,7 +343,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, - if (count == 0) - return -ENODATA; - if (count > bufsiz) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "invalid count value %x %zx\n", count, bufsiz); - return -E2BIG; - } -@@ -353,7 +353,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, - - rc = chip->ops->send(chip, (u8 *) buf, count); - if (rc < 0) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "tpm_transmit: tpm_send: error %zd\n", rc); - goto out; - } -@@ -372,7 +372,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, - goto out_recv; - - if (chip->ops->req_canceled(chip, status)) { -- dev_err(chip->pdev, "Operation Canceled\n"); -+ dev_err(&chip->dev, "Operation Canceled\n"); - rc = -ECANCELED; - goto out; - } -@@ -382,14 +382,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, - } while (time_before(jiffies, stop)); - - chip->ops->cancel(chip); -- dev_err(chip->pdev, "Operation Timed out\n"); -+ dev_err(&chip->dev, "Operation Timed out\n"); - rc = -ETIME; - goto out; - - out_recv: - rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); - if (rc < 0) -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "tpm_transmit: tpm_recv: error %zd\n", rc); - out: - if (!(flags & TPM_TRANSMIT_UNLOCKED)) -@@ -416,7 +416,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, - - err = be32_to_cpu(header->return_code); - if (err != 0 && desc) -- dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err, -+ dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, - desc); - - return err; -@@ -514,7 +514,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) - if (rc == TPM_ERR_INVALID_POSTINIT) { - /* The TPM is not started, we are the first to talk to it. - Execute a startup command. */ -- dev_info(chip->pdev, "Issuing TPM_STARTUP"); -+ dev_info(&chip->dev, "Issuing TPM_STARTUP"); - if (tpm_startup(chip, TPM_ST_CLEAR)) - return rc; - -@@ -526,7 +526,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) - 0, NULL); - } - if (rc) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "A TPM error (%zd) occurred attempting to determine the timeouts\n", - rc); - goto duration; -@@ -565,7 +565,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) - - /* Report adjusted timeouts */ - if (chip->vendor.timeout_adjusted) { -- dev_info(chip->pdev, -+ dev_info(&chip->dev, - HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", - old_timeout[0], new_timeout[0], - old_timeout[1], new_timeout[1], -@@ -612,7 +612,7 @@ duration: - chip->vendor.duration[TPM_MEDIUM] *= 1000; - chip->vendor.duration[TPM_LONG] *= 1000; - chip->vendor.duration_adjusted = true; -- dev_info(chip->pdev, "Adjusting TPM timeout parameters."); -+ dev_info(&chip->dev, "Adjusting TPM timeout parameters."); - } - return 0; - } -@@ -687,7 +687,7 @@ int tpm_is_tpm2(u32 chip_num) - - rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - - return rc; - } -@@ -716,7 +716,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) - rc = tpm2_pcr_read(chip, pcr_idx, res_buf); - else - rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return rc; - } - EXPORT_SYMBOL_GPL(tpm_pcr_read); -@@ -751,7 +751,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) - - if (chip->flags & TPM_CHIP_FLAG_TPM2) { - rc = tpm2_pcr_extend(chip, pcr_idx, hash); -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return rc; - } - -@@ -761,7 +761,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) - rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0, - "attempting extend a PCR value"); - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return rc; - } - EXPORT_SYMBOL_GPL(tpm_pcr_extend); -@@ -802,7 +802,9 @@ int tpm_do_selftest(struct tpm_chip *chip) - * around 300ms while the self test is ongoing, keep trying - * until the self test duration expires. */ - if (rc == -ETIME) { -- dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test"); -+ dev_info( -+ &chip->dev, HW_ERR -+ "TPM command timed out during continue self test"); - msleep(delay_msec); - continue; - } -@@ -812,7 +814,7 @@ int tpm_do_selftest(struct tpm_chip *chip) - - rc = be32_to_cpu(cmd.header.out.return_code); - if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { -- dev_info(chip->pdev, -+ dev_info(&chip->dev, - "TPM is disabled/deactivated (0x%X)\n", rc); - /* TPM is disabled and/or deactivated; driver can - * proceed and TPM does handle commands for -@@ -840,7 +842,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) - - rc = tpm_transmit_cmd(chip, cmd, buflen, 0, "attempting tpm_cmd"); - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return rc; - } - EXPORT_SYMBOL_GPL(tpm_send); -@@ -966,10 +968,10 @@ int tpm_pm_suspend(struct device *dev) - } - - if (rc) -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "Error (%d) sending savestate before suspend\n", rc); - else if (try > 0) -- dev_warn(chip->pdev, "TPM savestate took %dms\n", -+ dev_warn(&chip->dev, "TPM savestate took %dms\n", - try * TPM_TIMEOUT_RETRY); - - return rc; -@@ -1023,7 +1025,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) - - if (chip->flags & TPM_CHIP_FLAG_TPM2) { - err = tpm2_get_random(chip, out, max); -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return err; - } - -@@ -1045,7 +1047,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) - num_bytes -= recd; - } while (retries-- && total < max); - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return total ? total : -EIO; - } - EXPORT_SYMBOL_GPL(tpm_get_random); -@@ -1071,7 +1073,7 @@ int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload, - - rc = tpm2_seal_trusted(chip, payload, options); - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); - return rc; - } - EXPORT_SYMBOL_GPL(tpm_seal_trusted); -@@ -1097,7 +1099,8 @@ int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload, - - rc = tpm2_unseal_trusted(chip, payload, options); - -- tpm_chip_put(chip); -+ tpm_put_ops(chip); -+ - return rc; - } - EXPORT_SYMBOL_GPL(tpm_unseal_trusted); -diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c -index f880856aa75e..6a4056a3f7ee 100644 ---- a/drivers/char/tpm/tpm-sysfs.c -+++ b/drivers/char/tpm/tpm-sysfs.c -@@ -284,16 +284,28 @@ static const struct attribute_group tpm_dev_group = { - int tpm_sysfs_add_device(struct tpm_chip *chip) - { - int err; -- err = sysfs_create_group(&chip->pdev->kobj, -+ -+ /* XXX: If you wish to remove this restriction, you must first update -+ * tpm_sysfs to explicitly lock chip->ops. -+ */ -+ if (chip->flags & TPM_CHIP_FLAG_TPM2) -+ return 0; -+ -+ err = sysfs_create_group(&chip->dev.parent->kobj, - &tpm_dev_group); - - if (err) -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "failed to create sysfs attributes, %d\n", err); - return err; - } - - void tpm_sysfs_del_device(struct tpm_chip *chip) - { -- sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group); -+ /* The sysfs routines rely on an implicit tpm_try_get_ops, this -+ * function is called before ops is null'd and the sysfs core -+ * synchronizes this removal so that no callbacks are running or can -+ * run again -+ */ -+ sysfs_remove_group(&chip->dev.parent->kobj, &tpm_dev_group); - } -diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h -index 2216861f89f1..e21e2c599e66 100644 ---- a/drivers/char/tpm/tpm.h -+++ b/drivers/char/tpm/tpm.h -@@ -171,11 +171,16 @@ enum tpm_chip_flags { - }; - - struct tpm_chip { -- struct device *pdev; /* Device stuff */ - struct device dev; - struct cdev cdev; - -+ /* A driver callback under ops cannot be run unless ops_sem is held -+ * (sometimes implicitly, eg for the sysfs code). ops becomes null -+ * when the driver is unregistered, see tpm_try_get_ops. -+ */ -+ struct rw_semaphore ops_sem; - const struct tpm_class_ops *ops; -+ - unsigned int flags; - - int dev_num; /* /dev/tpm# */ -@@ -201,11 +206,6 @@ struct tpm_chip { - - #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) - --static inline void tpm_chip_put(struct tpm_chip *chip) --{ -- module_put(chip->pdev->driver->owner); --} -- - static inline int tpm_read_index(int base, int index) - { - outb(index, base); -@@ -517,6 +517,9 @@ extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, - wait_queue_head_t *, bool); - - struct tpm_chip *tpm_chip_find_get(int chip_num); -+__must_check int tpm_try_get_ops(struct tpm_chip *chip); -+void tpm_put_ops(struct tpm_chip *chip); -+ - extern struct tpm_chip *tpmm_chip_alloc(struct device *dev, - const struct tpm_class_ops *ops); - extern int tpm_chip_register(struct tpm_chip *chip); -diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c -index cb7e4f6b70ba..286bd090a488 100644 ---- a/drivers/char/tpm/tpm2-cmd.c -+++ b/drivers/char/tpm/tpm2-cmd.c -@@ -570,7 +570,7 @@ static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, - - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); - if (rc) { -- dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n", -+ dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n", - handle); - return; - } -@@ -580,7 +580,7 @@ static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, - "flushing context"); - if (rc) -- dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, -+ dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle, - rc); - - tpm_buf_destroy(&buf); -@@ -753,7 +753,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) - * except print the error code on a system failure. - */ - if (rc < 0) -- dev_warn(chip->pdev, "transmit returned %d while stopping the TPM", -+ dev_warn(&chip->dev, "transmit returned %d while stopping the TPM", - rc); - } - EXPORT_SYMBOL_GPL(tpm2_shutdown); -@@ -820,7 +820,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) - * immediately. This is a workaround for that. - */ - if (rc == TPM2_RC_TESTING) { -- dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n"); -+ dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n"); - rc = 0; - } - -diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c -index dfadad0916a1..a48a878f791d 100644 ---- a/drivers/char/tpm/tpm_atmel.c -+++ b/drivers/char/tpm/tpm_atmel.c -@@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) - for (i = 0; i < 6; i++) { - status = ioread8(chip->vendor.iobase + 1); - if ((status & ATML_STATUS_DATA_AVAIL) == 0) { -- dev_err(chip->pdev, "error reading header\n"); -+ dev_err(&chip->dev, "error reading header\n"); - return -EIO; - } - *buf++ = ioread8(chip->vendor.iobase); -@@ -60,12 +60,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) - size = be32_to_cpu(*native_size); - - if (count < size) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "Recv size(%d) less than available space\n", size); - for (; i < size; i++) { /* clear the waiting data anyway */ - status = ioread8(chip->vendor.iobase + 1); - if ((status & ATML_STATUS_DATA_AVAIL) == 0) { -- dev_err(chip->pdev, "error reading data\n"); -+ dev_err(&chip->dev, "error reading data\n"); - return -EIO; - } - } -@@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) - for (; i < size; i++) { - status = ioread8(chip->vendor.iobase + 1); - if ((status & ATML_STATUS_DATA_AVAIL) == 0) { -- dev_err(chip->pdev, "error reading data\n"); -+ dev_err(&chip->dev, "error reading data\n"); - return -EIO; - } - *buf++ = ioread8(chip->vendor.iobase); -@@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) - status = ioread8(chip->vendor.iobase + 1); - - if (status & ATML_STATUS_DATA_AVAIL) { -- dev_err(chip->pdev, "data available is stuck\n"); -+ dev_err(&chip->dev, "data available is stuck\n"); - return -EIO; - } - -@@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) - { - int i; - -- dev_dbg(chip->pdev, "tpm_atml_send:\n"); -+ dev_dbg(&chip->dev, "tpm_atml_send:\n"); - for (i = 0; i < count; i++) { -- dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); -+ dev_dbg(&chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); - iowrite8(buf[i], chip->vendor.iobase); - } - -diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c -index 8dfb88b9739c..dd8f0eb3170a 100644 ---- a/drivers/char/tpm/tpm_i2c_atmel.c -+++ b/drivers/char/tpm/tpm_i2c_atmel.c -@@ -52,7 +52,7 @@ struct priv_data { - static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) - { - struct priv_data *priv = chip->vendor.priv; -- struct i2c_client *client = to_i2c_client(chip->pdev); -+ struct i2c_client *client = to_i2c_client(chip->dev.parent); - s32 status; - - priv->len = 0; -@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) - - status = i2c_master_send(client, buf, len); - -- dev_dbg(chip->pdev, -+ dev_dbg(&chip->dev, - "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, - (int)min_t(size_t, 64, len), buf, len, status); - return status; -@@ -71,7 +71,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) - static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) - { - struct priv_data *priv = chip->vendor.priv; -- struct i2c_client *client = to_i2c_client(chip->pdev); -+ struct i2c_client *client = to_i2c_client(chip->dev.parent); - struct tpm_output_header *hdr = - (struct tpm_output_header *)priv->buffer; - u32 expected_len; -@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) - return -ENOMEM; - - if (priv->len >= expected_len) { -- dev_dbg(chip->pdev, -+ dev_dbg(&chip->dev, - "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, - (int)min_t(size_t, 64, expected_len), buf, count, - expected_len); -@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) - } - - rc = i2c_master_recv(client, buf, expected_len); -- dev_dbg(chip->pdev, -+ dev_dbg(&chip->dev, - "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, - (int)min_t(size_t, 64, expected_len), buf, count, - expected_len); -@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) - - static void i2c_atmel_cancel(struct tpm_chip *chip) - { -- dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported"); -+ dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported"); - } - - static u8 i2c_atmel_read_status(struct tpm_chip *chip) - { - struct priv_data *priv = chip->vendor.priv; -- struct i2c_client *client = to_i2c_client(chip->pdev); -+ struct i2c_client *client = to_i2c_client(chip->dev.parent); - int rc; - - /* The TPM fails the I2C read until it is ready, so we do the entire -@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip) - /* Once the TPM has completed the command the command remains readable - * until another command is issued. */ - rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); -- dev_dbg(chip->pdev, -+ dev_dbg(&chip->dev, - "%s: sts=%d", __func__, rc); - if (rc <= 0) - return 0; -diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c -index 63d5d22e9e60..f2aa99e34b4b 100644 ---- a/drivers/char/tpm/tpm_i2c_infineon.c -+++ b/drivers/char/tpm/tpm_i2c_infineon.c -@@ -446,7 +446,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) - /* read first 10 bytes, including tag, paramsize, and result */ - size = recv_data(chip, buf, TPM_HEADER_SIZE); - if (size < TPM_HEADER_SIZE) { -- dev_err(chip->pdev, "Unable to read header\n"); -+ dev_err(&chip->dev, "Unable to read header\n"); - goto out; - } - -@@ -459,14 +459,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) - size += recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); - if (size < expected) { -- dev_err(chip->pdev, "Unable to read remainder of result\n"); -+ dev_err(&chip->dev, "Unable to read remainder of result\n"); - size = -ETIME; - goto out; - } - - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ -- dev_err(chip->pdev, "Error left over data\n"); -+ dev_err(&chip->dev, "Error left over data\n"); - size = -EIO; - goto out; - } -diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c -index 847f1597fe9b..a1e1474dda30 100644 ---- a/drivers/char/tpm/tpm_i2c_nuvoton.c -+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c -@@ -96,13 +96,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size, - /* read TPM_STS register */ - static u8 i2c_nuvoton_read_status(struct tpm_chip *chip) - { -- struct i2c_client *client = to_i2c_client(chip->pdev); -+ struct i2c_client *client = to_i2c_client(chip->dev.parent); - s32 status; - u8 data; - - status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); - if (status <= 0) { -- dev_err(chip->pdev, "%s() error return %d\n", __func__, -+ dev_err(&chip->dev, "%s() error return %d\n", __func__, - status); - data = TPM_STS_ERR_VAL; - } -@@ -127,13 +127,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) - /* write commandReady to TPM_STS register */ - static void i2c_nuvoton_ready(struct tpm_chip *chip) - { -- struct i2c_client *client = to_i2c_client(chip->pdev); -+ struct i2c_client *client = to_i2c_client(chip->dev.parent); - s32 status; - - /* this causes the current command to be aborted */ - status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY); - if (status < 0) -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "%s() fail to write TPM_STS.commandReady\n", __func__); - } - -@@ -212,7 +212,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, - return 0; - } while (time_before(jiffies, stop)); - } -- dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask, -+ dev_err(&chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask, - value); - return -ETIMEDOUT; - } -@@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, - &chip->vendor.read_queue) == 0) { - burst_count = i2c_nuvoton_get_burstcount(client, chip); - if (burst_count < 0) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "%s() fail to read burstCount=%d\n", __func__, - burst_count); - return -EIO; -@@ -249,12 +249,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, - rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R, - bytes2read, &buf[size]); - if (rc < 0) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "%s() fail on i2c_nuvoton_read_buf()=%d\n", - __func__, rc); - return -EIO; - } -- dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read); -+ dev_dbg(&chip->dev, "%s(%d):", __func__, bytes2read); - size += bytes2read; - } - -@@ -264,7 +264,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, - /* Read TPM command results */ - static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) - { -- struct device *dev = chip->pdev; -+ struct device *dev = chip->dev.parent; - struct i2c_client *client = to_i2c_client(dev); - s32 rc; - int expected, status, burst_count, retries, size = 0; -@@ -334,7 +334,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) - break; - } - i2c_nuvoton_ready(chip); -- dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size); -+ dev_dbg(&chip->dev, "%s() -> %d\n", __func__, size); - return size; - } - -@@ -347,7 +347,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) - */ - static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) - { -- struct device *dev = chip->pdev; -+ struct device *dev = chip->dev.parent; - struct i2c_client *client = to_i2c_client(dev); - u32 ordinal; - size_t count = 0; -diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c -index 6c488e635fdd..e3cf9f3545c5 100644 ---- a/drivers/char/tpm/tpm_infineon.c -+++ b/drivers/char/tpm/tpm_infineon.c -@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) - } - if (i == TPM_MAX_TRIES) { /* timeout occurs */ - if (wait_for_bit == STAT_XFE) -- dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n"); -+ dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n"); - if (wait_for_bit == STAT_RDA) -- dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n"); -+ dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n"); - return -EIO; - } - return 0; -@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) - static void tpm_wtx(struct tpm_chip *chip) - { - number_of_wtx++; -- dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n", -+ dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n", - number_of_wtx, TPM_MAX_WTX_PACKAGES); - wait_and_send(chip, TPM_VL_VER); - wait_and_send(chip, TPM_CTRL_WTX); -@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip) - - static void tpm_wtx_abort(struct tpm_chip *chip) - { -- dev_info(chip->pdev, "Aborting WTX\n"); -+ dev_info(&chip->dev, "Aborting WTX\n"); - wait_and_send(chip, TPM_VL_VER); - wait_and_send(chip, TPM_CTRL_WTX_ABORT); - wait_and_send(chip, 0x00); -@@ -257,7 +257,7 @@ recv_begin: - } - - if (buf[0] != TPM_VL_VER) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "Wrong transport protocol implementation!\n"); - return -EIO; - } -@@ -272,7 +272,7 @@ recv_begin: - } - - if ((size == 0x6D00) && (buf[1] == 0x80)) { -- dev_err(chip->pdev, "Error handling on vendor layer!\n"); -+ dev_err(&chip->dev, "Error handling on vendor layer!\n"); - return -EIO; - } - -@@ -284,7 +284,7 @@ recv_begin: - } - - if (buf[1] == TPM_CTRL_WTX) { -- dev_info(chip->pdev, "WTX-package received\n"); -+ dev_info(&chip->dev, "WTX-package received\n"); - if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { - tpm_wtx(chip); - goto recv_begin; -@@ -295,14 +295,14 @@ recv_begin: - } - - if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { -- dev_info(chip->pdev, "WTX-abort acknowledged\n"); -+ dev_info(&chip->dev, "WTX-abort acknowledged\n"); - return size; - } - - if (buf[1] == TPM_CTRL_ERROR) { -- dev_err(chip->pdev, "ERROR-package received:\n"); -+ dev_err(&chip->dev, "ERROR-package received:\n"); - if (buf[4] == TPM_INF_NAK) -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "-> Negative acknowledgement" - " - retransmit command!\n"); - return -EIO; -@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) - - ret = empty_fifo(chip, 1); - if (ret) { -- dev_err(chip->pdev, "Timeout while clearing FIFO\n"); -+ dev_err(&chip->dev, "Timeout while clearing FIFO\n"); - return -EIO; - } - -diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c -index 289389ecef84..766370bed60c 100644 ---- a/drivers/char/tpm/tpm_nsc.c -+++ b/drivers/char/tpm/tpm_nsc.c -@@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) - } - while (time_before(jiffies, stop)); - -- dev_info(chip->pdev, "wait for ready failed\n"); -+ dev_info(&chip->dev, "wait for ready failed\n"); - return -EBUSY; - } - -@@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) - return -EIO; - - if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { -- dev_err(chip->pdev, "F0 timeout\n"); -+ dev_err(&chip->dev, "F0 timeout\n"); - return -EIO; - } - if ((data = - inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { -- dev_err(chip->pdev, "not in normal mode (0x%x)\n", -+ dev_err(&chip->dev, "not in normal mode (0x%x)\n", - data); - return -EIO; - } -@@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) - for (p = buffer; p < &buffer[count]; p++) { - if (wait_for_stat - (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "OBF timeout (while reading data)\n"); - return -EIO; - } -@@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) - - if ((data & NSC_STATUS_F0) == 0 && - (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { -- dev_err(chip->pdev, "F0 not set\n"); -+ dev_err(&chip->dev, "F0 not set\n"); - return -EIO; - } - if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "expected end of command(0x%x)\n", data); - return -EIO; - } -@@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) - return -EIO; - - if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { -- dev_err(chip->pdev, "IBF timeout\n"); -+ dev_err(&chip->dev, "IBF timeout\n"); - return -EIO; - } - - outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); - if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { -- dev_err(chip->pdev, "IBR timeout\n"); -+ dev_err(&chip->dev, "IBR timeout\n"); - return -EIO; - } - - for (i = 0; i < count; i++) { - if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - "IBF timeout (while writing data)\n"); - return -EIO; - } -@@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) - } - - if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { -- dev_err(chip->pdev, "IBF timeout\n"); -+ dev_err(&chip->dev, "IBF timeout\n"); - return -EIO; - } - outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); -diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c -index f10a107614b4..7f13221aeb30 100644 ---- a/drivers/char/tpm/tpm_tis.c -+++ b/drivers/char/tpm/tpm_tis.c -@@ -293,7 +293,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) - /* read first 10 bytes, including tag, paramsize, and result */ - if ((size = - recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { -- dev_err(chip->pdev, "Unable to read header\n"); -+ dev_err(&chip->dev, "Unable to read header\n"); - goto out; - } - -@@ -306,7 +306,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) - if ((size += - recv_data(chip, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE)) < expected) { -- dev_err(chip->pdev, "Unable to read remainder of result\n"); -+ dev_err(&chip->dev, "Unable to read remainder of result\n"); - size = -ETIME; - goto out; - } -@@ -315,7 +315,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) - &chip->vendor.int_queue, false); - status = tpm_tis_status(chip); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ -- dev_err(chip->pdev, "Error left over data\n"); -+ dev_err(&chip->dev, "Error left over data\n"); - size = -EIO; - goto out; - } -@@ -401,7 +401,7 @@ static void disable_interrupts(struct tpm_chip *chip) - iowrite32(intmask, - chip->vendor.iobase + - TPM_INT_ENABLE(chip->vendor.locality)); -- devm_free_irq(chip->pdev, chip->vendor.irq, chip); -+ devm_free_irq(&chip->dev, chip->vendor.irq, chip); - chip->vendor.irq = 0; - } - -@@ -463,7 +463,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) - msleep(1); - if (!priv->irq_tested) { - disable_interrupts(chip); -- dev_err(chip->pdev, -+ dev_err(&chip->dev, - FW_BUG "TPM interrupt not working, polling instead\n"); - } - priv->irq_tested = true; -@@ -533,7 +533,7 @@ static int probe_itpm(struct tpm_chip *chip) - - rc = tpm_tis_send_data(chip, cmd_getticks, len); - if (rc == 0) { -- dev_info(chip->pdev, "Detected an iTPM.\n"); -+ dev_info(&chip->dev, "Detected an iTPM.\n"); - rc = 1; - } else - rc = -EFAULT; -@@ -766,7 +766,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, - if (devm_request_irq - (dev, i, tis_int_probe, IRQF_SHARED, - chip->devname, chip) != 0) { -- dev_info(chip->pdev, -+ dev_info(&chip->dev, - "Unable to request irq: %d for probe\n", - i); - continue; -@@ -818,7 +818,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, - if (devm_request_irq - (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED, - chip->devname, chip) != 0) { -- dev_info(chip->pdev, -+ dev_info(&chip->dev, - "Unable to request irq: %d for use\n", - chip->vendor.irq); - chip->vendor.irq = 0; -diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c -index 0dadb6332f0e..7abe908427df 100644 ---- a/drivers/crypto/atmel-sha.c -+++ b/drivers/crypto/atmel-sha.c -@@ -963,7 +963,9 @@ static int atmel_sha_finup(struct ahash_request *req) - ctx->flags |= SHA_FLAGS_FINUP; - - err1 = atmel_sha_update(req); -- if (err1 == -EINPROGRESS || err1 == -EBUSY) -+ if (err1 == -EINPROGRESS || -+ (err1 == -EBUSY && (ahash_request_flags(req) & -+ CRYPTO_TFM_REQ_MAY_BACKLOG))) - return err1; - - /* -diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c -index 99d5e11db194..e06cc5df30be 100644 ---- a/drivers/crypto/caam/caamhash.c -+++ b/drivers/crypto/caam/caamhash.c -@@ -498,7 +498,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in, - ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); - if (!ret) { - /* in progress */ -- wait_for_completion_interruptible(&result.completion); -+ wait_for_completion(&result.completion); - ret = result.err; - #ifdef DEBUG - print_hex_dump(KERN_ERR, -diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c -index e1eaf4ff9762..3ce1d5cdcbd2 100644 ---- a/drivers/crypto/caam/key_gen.c -+++ b/drivers/crypto/caam/key_gen.c -@@ -103,7 +103,7 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, - ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); - if (!ret) { - /* in progress */ -- wait_for_completion_interruptible(&result.completion); -+ wait_for_completion(&result.completion); - ret = result.err; - #ifdef DEBUG - print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", -diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c -index 9a8a18aafd5c..6a60936b46e0 100644 ---- a/drivers/crypto/talitos.c -+++ b/drivers/crypto/talitos.c -@@ -804,7 +804,7 @@ static void talitos_unregister_rng(struct device *dev) - * crypto alg - */ - #define TALITOS_CRA_PRIORITY 3000 --#define TALITOS_MAX_KEY_SIZE 96 -+#define TALITOS_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE) - #define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ - - struct talitos_ctx { -@@ -1388,6 +1388,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher, - { - struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher); - -+ if (keylen > TALITOS_MAX_KEY_SIZE) { -+ crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+ } -+ - memcpy(&ctx->key, key, keylen); - ctx->keylen = keylen; - -diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c -index e33c729b9f48..5a1490b046ac 100644 ---- a/drivers/irqchip/irq-gic-v3.c -+++ b/drivers/irqchip/irq-gic-v3.c -@@ -632,6 +632,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, - int enabled; - u64 val; - -+ if (cpu >= nr_cpu_ids) -+ return -EINVAL; -+ - if (gic_irq_in_rdist(d)) - return -EINVAL; - -diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c -index 84b9cca152eb..e83acc608678 100644 ---- a/drivers/net/phy/dp83640.c -+++ b/drivers/net/phy/dp83640.c -@@ -907,7 +907,7 @@ static void decode_txts(struct dp83640_private *dp83640, - if (overflow) { - pr_debug("tx timestamp queue overflow, count %d\n", overflow); - while (skb) { -- skb_complete_tx_timestamp(skb, NULL); -+ kfree_skb(skb); - skb = skb_dequeue(&dp83640->tx_queue); - } - return; -diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c -index e13ad6cdcc22..c8b85f1069ff 100644 ---- a/drivers/net/phy/micrel.c -+++ b/drivers/net/phy/micrel.c -@@ -539,6 +539,8 @@ static int ksz9031_read_status(struct phy_device *phydev) - if ((regval & 0xFF) == 0xFF) { - phy_init_hw(phydev); - phydev->link = 0; -+ if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev)) -+ phydev->drv->config_intr(phydev); - } - - return 0; -diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c -index 349aecbc210a..ac945f8781ac 100644 ---- a/drivers/net/vrf.c -+++ b/drivers/net/vrf.c -@@ -733,15 +733,15 @@ static int vrf_del_slave(struct net_device *dev, struct net_device *port_dev) - static void vrf_dev_uninit(struct net_device *dev) - { - struct net_vrf *vrf = netdev_priv(dev); -- struct slave_queue *queue = &vrf->queue; -- struct list_head *head = &queue->all_slaves; -- struct slave *slave, *next; -+// struct slave_queue *queue = &vrf->queue; -+// struct list_head *head = &queue->all_slaves; -+// struct slave *slave, *next; - - vrf_rtable_destroy(vrf); - vrf_rt6_destroy(vrf); - -- list_for_each_entry_safe(slave, next, head, list) -- vrf_del_slave(dev, slave->dev); -+// list_for_each_entry_safe(slave, next, head, list) -+// vrf_del_slave(dev, slave->dev); - - free_percpu(dev->dstats); - dev->dstats = NULL; -@@ -914,6 +914,14 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[]) - - static void vrf_dellink(struct net_device *dev, struct list_head *head) - { -+ struct net_vrf *vrf = netdev_priv(dev); -+ struct slave_queue *queue = &vrf->queue; -+ struct list_head *all_slaves = &queue->all_slaves; -+ struct slave *slave, *next; -+ -+ list_for_each_entry_safe(slave, next, all_slaves, list) -+ vrf_del_slave(dev, slave->dev); -+ - unregister_netdevice_queue(dev, head); - } - -diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -index 70a6985334d5..da5826d788d6 100644 ---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -@@ -4472,6 +4472,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, - GFP_KERNEL); - } else if (ieee80211_is_action(mgmt->frame_control)) { -+ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { -+ brcmf_err("invalid action frame length\n"); -+ err = -EINVAL; -+ goto exit; -+ } - af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); - if (af_params == NULL) { - brcmf_err("unable to allocate frame\n"); -diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c -index 8e11fb2831cd..34f1d6b41fb9 100644 ---- a/drivers/parisc/ccio-dma.c -+++ b/drivers/parisc/ccio-dma.c -@@ -741,6 +741,8 @@ ccio_map_single(struct device *dev, void *addr, size_t size, - - BUG_ON(!dev); - ioc = GET_IOC(dev); -+ if (!ioc) -+ return DMA_ERROR_CODE; - - BUG_ON(size <= 0); - -@@ -805,6 +807,10 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size, - - BUG_ON(!dev); - ioc = GET_IOC(dev); -+ if (!ioc) { -+ WARN_ON(!ioc); -+ return; -+ } - - DBG_RUN("%s() iovp 0x%lx/%x\n", - __func__, (long)iova, size); -@@ -908,6 +914,8 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, - - BUG_ON(!dev); - ioc = GET_IOC(dev); -+ if (!ioc) -+ return 0; - - DBG_RUN_SG("%s() START %d entries\n", __func__, nents); - -@@ -980,6 +988,10 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, - - BUG_ON(!dev); - ioc = GET_IOC(dev); -+ if (!ioc) { -+ WARN_ON(!ioc); -+ return; -+ } - - DBG_RUN_SG("%s() START %d entries, %p,%x\n", - __func__, nents, sg_virt(sglist), sglist->length); -diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c -index a0580afe1713..7b0ca1551d7b 100644 ---- a/drivers/parisc/dino.c -+++ b/drivers/parisc/dino.c -@@ -154,7 +154,10 @@ struct dino_device - }; - - /* Looks nice and keeps the compiler happy */ --#define DINO_DEV(d) ((struct dino_device *) d) -+#define DINO_DEV(d) ({ \ -+ void *__pdata = d; \ -+ BUG_ON(!__pdata); \ -+ (struct dino_device *)__pdata; }) - - - /* -diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c -index 42844c2bc065..d0c2759076a2 100644 ---- a/drivers/parisc/lba_pci.c -+++ b/drivers/parisc/lba_pci.c -@@ -111,8 +111,10 @@ static u32 lba_t32; - - - /* Looks nice and keeps the compiler happy */ --#define LBA_DEV(d) ((struct lba_device *) (d)) -- -+#define LBA_DEV(d) ({ \ -+ void *__pdata = d; \ -+ BUG_ON(!__pdata); \ -+ (struct lba_device *)__pdata; }) - - /* - ** Only allow 8 subsidiary busses per LBA -diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c -index 225049b492e5..d6326144ce01 100644 ---- a/drivers/parisc/sba_iommu.c -+++ b/drivers/parisc/sba_iommu.c -@@ -691,6 +691,8 @@ static int sba_dma_supported( struct device *dev, u64 mask) - return 0; - - ioc = GET_IOC(dev); -+ if (!ioc) -+ return 0; - - /* - * check if mask is >= than the current max IO Virt Address -@@ -722,6 +724,8 @@ sba_map_single(struct device *dev, void *addr, size_t size, - int pide; - - ioc = GET_IOC(dev); -+ if (!ioc) -+ return DMA_ERROR_CODE; - - /* save offset bits */ - offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK; -@@ -803,6 +807,10 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, - DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); - - ioc = GET_IOC(dev); -+ if (!ioc) { -+ WARN_ON(!ioc); -+ return; -+ } - offset = iova & ~IOVP_MASK; - iova ^= offset; /* clear offset bits */ - size += offset; -@@ -942,6 +950,8 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, - DBG_RUN_SG("%s() START %d entries\n", __func__, nents); - - ioc = GET_IOC(dev); -+ if (!ioc) -+ return 0; - - /* Fast path single entry scatterlists. */ - if (nents == 1) { -@@ -1027,6 +1037,10 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, - __func__, nents, sg_virt(sglist), sglist->length); - - ioc = GET_IOC(dev); -+ if (!ioc) { -+ WARN_ON(!ioc); -+ return; -+ } - - #ifdef SBA_COLLECT_STATS - ioc->usg_calls++; -diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c -index 5ab54ef4f304..e4f69bddcfb1 100644 ---- a/drivers/tty/vt/vt.c -+++ b/drivers/tty/vt/vt.c -@@ -2708,13 +2708,13 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) - * related to the kernel should not use this. - */ - data = vt_get_shift_state(); -- ret = __put_user(data, p); -+ ret = put_user(data, p); - break; - case TIOCL_GETMOUSEREPORTING: - console_lock(); /* May be overkill */ - data = mouse_reporting(); - console_unlock(); -- ret = __put_user(data, p); -+ ret = put_user(data, p); - break; - case TIOCL_SETVESABLANK: - console_lock(); -@@ -2723,7 +2723,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) - break; - case TIOCL_GETKMSGREDIRECT: - data = vt_get_kmsg_redirect(); -- ret = __put_user(data, p); -+ ret = put_user(data, p); - break; - case TIOCL_SETKMSGREDIRECT: - if (!capable(CAP_SYS_ADMIN)) { -diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c -index 29ef427c0652..f44e93d2650d 100644 ---- a/fs/binfmt_elf.c -+++ b/fs/binfmt_elf.c -@@ -905,17 +905,60 @@ static int load_elf_binary(struct linux_binprm *bprm) - elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; - - vaddr = elf_ppnt->p_vaddr; -+ /* -+ * If we are loading ET_EXEC or we have already performed -+ * the ET_DYN load_addr calculations, proceed normally. -+ */ - if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { - elf_flags |= MAP_FIXED; - } else if (loc->elf_ex.e_type == ET_DYN) { -- /* Try and get dynamic programs out of the way of the -- * default mmap base, as well as whatever program they -- * might try to exec. This is because the brk will -- * follow the loader, and is not movable. */ -- load_bias = ELF_ET_DYN_BASE - vaddr; -- if (current->flags & PF_RANDOMIZE) -- load_bias += arch_mmap_rnd(); -- load_bias = ELF_PAGESTART(load_bias); -+ /* -+ * This logic is run once for the first LOAD Program -+ * Header for ET_DYN binaries to calculate the -+ * randomization (load_bias) for all the LOAD -+ * Program Headers, and to calculate the entire -+ * size of the ELF mapping (total_size). (Note that -+ * load_addr_set is set to true later once the -+ * initial mapping is performed.) -+ * -+ * There are effectively two types of ET_DYN -+ * binaries: programs (i.e. PIE: ET_DYN with INTERP) -+ * and loaders (ET_DYN without INTERP, since they -+ * _are_ the ELF interpreter). The loaders must -+ * be loaded away from programs since the program -+ * may otherwise collide with the loader (especially -+ * for ET_EXEC which does not have a randomized -+ * position). For example to handle invocations of -+ * "./ld.so someprog" to test out a new version of -+ * the loader, the subsequent program that the -+ * loader loads must avoid the loader itself, so -+ * they cannot share the same load range. Sufficient -+ * room for the brk must be allocated with the -+ * loader as well, since brk must be available with -+ * the loader. -+ * -+ * Therefore, programs are loaded offset from -+ * ELF_ET_DYN_BASE and loaders are loaded into the -+ * independently randomized mmap region (0 load_bias -+ * without MAP_FIXED). -+ */ -+ if (elf_interpreter) { -+ load_bias = ELF_ET_DYN_BASE; -+ if (current->flags & PF_RANDOMIZE) -+ load_bias += arch_mmap_rnd(); -+ elf_flags |= MAP_FIXED; -+ } else -+ load_bias = 0; -+ -+ /* -+ * Since load_bias is used for all subsequent loading -+ * calculations, we must lower it by the first vaddr -+ * so that the remaining calculations based on the -+ * ELF vaddrs will be correctly offset. The result -+ * is then page aligned. -+ */ -+ load_bias = ELF_PAGESTART(load_bias - vaddr); -+ - total_size = total_mapping_size(elf_phdata, - loc->elf_ex.e_phnum); - if (!total_size) { -diff --git a/fs/dcache.c b/fs/dcache.c -index 849c1c1e787b..3000cbb54949 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1128,11 +1128,12 @@ void shrink_dcache_sb(struct super_block *sb) - LIST_HEAD(dispose); - - freed = list_lru_walk(&sb->s_dentry_lru, -- dentry_lru_isolate_shrink, &dispose, UINT_MAX); -+ dentry_lru_isolate_shrink, &dispose, 1024); - - this_cpu_sub(nr_dentry_unused, freed); - shrink_dentry_list(&dispose); -- } while (freed > 0); -+ cond_resched(); -+ } while (list_lru_count(&sb->s_dentry_lru) > 0); - } - EXPORT_SYMBOL(shrink_dcache_sb); - -diff --git a/fs/exec.c b/fs/exec.c -index 02153068a694..9c5ee2a880aa 100644 ---- a/fs/exec.c -+++ b/fs/exec.c -@@ -206,8 +206,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, - - if (write) { - unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; -- unsigned long ptr_size; -- struct rlimit *rlim; -+ unsigned long ptr_size, limit; - - /* - * Since the stack will hold pointers to the strings, we -@@ -236,14 +235,16 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, - return page; - - /* -- * Limit to 1/4-th the stack size for the argv+env strings. -+ * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM -+ * (whichever is smaller) for the argv+env strings. - * This ensures that: - * - the remaining binfmt code will not run out of stack space, - * - the program will have a reasonable amount of stack left - * to work from. - */ -- rlim = current->signal->rlim; -- if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) -+ limit = _STK_LIM / 4 * 3; -+ limit = min(limit, rlimit(RLIMIT_STACK) / 4); -+ if (size > limit) - goto fail; - } - -diff --git a/fs/mount.h b/fs/mount.h -index 13a4ebbbaa74..37c64bbe840c 100644 ---- a/fs/mount.h -+++ b/fs/mount.h -@@ -57,6 +57,7 @@ struct mount { - struct mnt_namespace *mnt_ns; /* containing namespace */ - struct mountpoint *mnt_mp; /* where is it mounted */ - struct hlist_node mnt_mp_list; /* list mounts with the same mountpoint */ -+ struct list_head mnt_umounting; /* list entry for umount propagation */ - #ifdef CONFIG_FSNOTIFY - struct hlist_head mnt_fsnotify_marks; - __u32 mnt_fsnotify_mask; -diff --git a/fs/namespace.c b/fs/namespace.c -index f26d18d69712..ec4078d16eb7 100644 ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -237,6 +237,7 @@ static struct mount *alloc_vfsmnt(const char *name) - INIT_LIST_HEAD(&mnt->mnt_slave_list); - INIT_LIST_HEAD(&mnt->mnt_slave); - INIT_HLIST_NODE(&mnt->mnt_mp_list); -+ INIT_LIST_HEAD(&mnt->mnt_umounting); - #ifdef CONFIG_FSNOTIFY - INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); - #endif -diff --git a/fs/pnode.c b/fs/pnode.c -index b394ca5307ec..d15c63e97ef1 100644 ---- a/fs/pnode.c -+++ b/fs/pnode.c -@@ -24,6 +24,11 @@ static inline struct mount *first_slave(struct mount *p) - return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave); - } - -+static inline struct mount *last_slave(struct mount *p) -+{ -+ return list_entry(p->mnt_slave_list.prev, struct mount, mnt_slave); -+} -+ - static inline struct mount *next_slave(struct mount *p) - { - return list_entry(p->mnt_slave.next, struct mount, mnt_slave); -@@ -164,6 +169,19 @@ static struct mount *propagation_next(struct mount *m, - } - } - -+static struct mount *skip_propagation_subtree(struct mount *m, -+ struct mount *origin) -+{ -+ /* -+ * Advance m such that propagation_next will not return -+ * the slaves of m. -+ */ -+ if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) -+ m = last_slave(m); -+ -+ return m; -+} -+ - static struct mount *next_group(struct mount *m, struct mount *origin) - { - while (1) { -@@ -415,65 +433,104 @@ void propagate_mount_unlock(struct mount *mnt) - } - } - --/* -- * Mark all mounts that the MNT_LOCKED logic will allow to be unmounted. -- */ --static void mark_umount_candidates(struct mount *mnt) -+static void umount_one(struct mount *mnt, struct list_head *to_umount) - { -- struct mount *parent = mnt->mnt_parent; -- struct mount *m; -- -- BUG_ON(parent == mnt); -- -- for (m = propagation_next(parent, parent); m; -- m = propagation_next(m, parent)) { -- struct mount *child = __lookup_mnt(&m->mnt, -- mnt->mnt_mountpoint); -- if (!child || (child->mnt.mnt_flags & MNT_UMOUNT)) -- continue; -- if (!IS_MNT_LOCKED(child) || IS_MNT_MARKED(m)) { -- SET_MNT_MARK(child); -- } -- } -+ CLEAR_MNT_MARK(mnt); -+ mnt->mnt.mnt_flags |= MNT_UMOUNT; -+ list_del_init(&mnt->mnt_child); -+ list_del_init(&mnt->mnt_umounting); -+ list_move_tail(&mnt->mnt_list, to_umount); - } - - /* - * NOTE: unmounting 'mnt' naturally propagates to all other mounts its - * parent propagates to. - */ --static void __propagate_umount(struct mount *mnt) -+static bool __propagate_umount(struct mount *mnt, -+ struct list_head *to_umount, -+ struct list_head *to_restore) - { -- struct mount *parent = mnt->mnt_parent; -- struct mount *m; -+ bool progress = false; -+ struct mount *child; - -- BUG_ON(parent == mnt); -+ /* -+ * The state of the parent won't change if this mount is -+ * already unmounted or marked as without children. -+ */ -+ if (mnt->mnt.mnt_flags & (MNT_UMOUNT | MNT_MARKED)) -+ goto out; - -- for (m = propagation_next(parent, parent); m; -- m = propagation_next(m, parent)) { -- struct mount *topper; -- struct mount *child = __lookup_mnt(&m->mnt, -- mnt->mnt_mountpoint); -- /* -- * umount the child only if the child has no children -- * and the child is marked safe to unmount. -- */ -- if (!child || !IS_MNT_MARKED(child)) -+ /* Verify topper is the only grandchild that has not been -+ * speculatively unmounted. -+ */ -+ list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { -+ if (child->mnt_mountpoint == mnt->mnt.mnt_root) - continue; -- CLEAR_MNT_MARK(child); -+ if (!list_empty(&child->mnt_umounting) && IS_MNT_MARKED(child)) -+ continue; -+ /* Found a mounted child */ -+ goto children; -+ } - -- /* If there is exactly one mount covering all of child -- * replace child with that mount. -- */ -- topper = find_topper(child); -- if (topper) -- mnt_change_mountpoint(child->mnt_parent, child->mnt_mp, -- topper); -+ /* Mark mounts that can be unmounted if not locked */ -+ SET_MNT_MARK(mnt); -+ progress = true; -+ -+ /* If a mount is without children and not locked umount it. */ -+ if (!IS_MNT_LOCKED(mnt)) { -+ umount_one(mnt, to_umount); -+ } else { -+children: -+ list_move_tail(&mnt->mnt_umounting, to_restore); -+ } -+out: -+ return progress; -+} -+ -+static void umount_list(struct list_head *to_umount, -+ struct list_head *to_restore) -+{ -+ struct mount *mnt, *child, *tmp; -+ list_for_each_entry(mnt, to_umount, mnt_list) { -+ list_for_each_entry_safe(child, tmp, &mnt->mnt_mounts, mnt_child) { -+ /* topper? */ -+ if (child->mnt_mountpoint == mnt->mnt.mnt_root) -+ list_move_tail(&child->mnt_umounting, to_restore); -+ else -+ umount_one(child, to_umount); -+ } -+ } -+} - -- if (list_empty(&child->mnt_mounts)) { -- list_del_init(&child->mnt_child); -- child->mnt.mnt_flags |= MNT_UMOUNT; -- list_move_tail(&child->mnt_list, &mnt->mnt_list); -+static void restore_mounts(struct list_head *to_restore) -+{ -+ /* Restore mounts to a clean working state */ -+ while (!list_empty(to_restore)) { -+ struct mount *mnt, *parent; -+ struct mountpoint *mp; -+ -+ mnt = list_first_entry(to_restore, struct mount, mnt_umounting); -+ CLEAR_MNT_MARK(mnt); -+ list_del_init(&mnt->mnt_umounting); -+ -+ /* Should this mount be reparented? */ -+ mp = mnt->mnt_mp; -+ parent = mnt->mnt_parent; -+ while (parent->mnt.mnt_flags & MNT_UMOUNT) { -+ mp = parent->mnt_mp; -+ parent = parent->mnt_parent; - } -+ if (parent != mnt->mnt_parent) -+ mnt_change_mountpoint(parent, mp, mnt); -+ } -+} -+ -+static void cleanup_umount_visitations(struct list_head *visited) -+{ -+ while (!list_empty(visited)) { -+ struct mount *mnt = -+ list_first_entry(visited, struct mount, mnt_umounting); -+ list_del_init(&mnt->mnt_umounting); - } - } - -@@ -487,11 +544,68 @@ static void __propagate_umount(struct mount *mnt) - int propagate_umount(struct list_head *list) - { - struct mount *mnt; -+ LIST_HEAD(to_restore); -+ LIST_HEAD(to_umount); -+ LIST_HEAD(visited); -+ -+ /* Find candidates for unmounting */ -+ list_for_each_entry_reverse(mnt, list, mnt_list) { -+ struct mount *parent = mnt->mnt_parent; -+ struct mount *m; -+ -+ /* -+ * If this mount has already been visited it is known that it's -+ * entire peer group and all of their slaves in the propagation -+ * tree for the mountpoint has already been visited and there is -+ * no need to visit them again. -+ */ -+ if (!list_empty(&mnt->mnt_umounting)) -+ continue; -+ -+ list_add_tail(&mnt->mnt_umounting, &visited); -+ for (m = propagation_next(parent, parent); m; -+ m = propagation_next(m, parent)) { -+ struct mount *child = __lookup_mnt(&m->mnt, -+ mnt->mnt_mountpoint); -+ if (!child) -+ continue; -+ -+ if (!list_empty(&child->mnt_umounting)) { -+ /* -+ * If the child has already been visited it is -+ * know that it's entire peer group and all of -+ * their slaves in the propgation tree for the -+ * mountpoint has already been visited and there -+ * is no need to visit this subtree again. -+ */ -+ m = skip_propagation_subtree(m, parent); -+ continue; -+ } else if (child->mnt.mnt_flags & MNT_UMOUNT) { -+ /* -+ * We have come accross an partially unmounted -+ * mount in list that has not been visited yet. -+ * Remember it has been visited and continue -+ * about our merry way. -+ */ -+ list_add_tail(&child->mnt_umounting, &visited); -+ continue; -+ } -+ -+ /* Check the child and parents while progress is made */ -+ while (__propagate_umount(child, -+ &to_umount, &to_restore)) { -+ /* Is the parent a umount candidate? */ -+ child = child->mnt_parent; -+ if (list_empty(&child->mnt_umounting)) -+ break; -+ } -+ } -+ } - -- list_for_each_entry_reverse(mnt, list, mnt_list) -- mark_umount_candidates(mnt); -+ umount_list(&to_umount, &to_restore); -+ restore_mounts(&to_restore); -+ cleanup_umount_visitations(&visited); -+ list_splice_tail(&to_umount, list); - -- list_for_each_entry(mnt, list, mnt_list) -- __propagate_umount(mnt); - return 0; - } -diff --git a/include/linux/device.h b/include/linux/device.h -index b8f411b57dcb..7075a2485ed3 100644 ---- a/include/linux/device.h -+++ b/include/linux/device.h -@@ -368,6 +368,7 @@ int subsys_virtual_register(struct bus_type *subsys, - * @suspend: Used to put the device to sleep mode, usually to a low power - * state. - * @resume: Used to bring the device from the sleep mode. -+ * @shutdown: Called at shut-down time to quiesce the device. - * @ns_type: Callbacks so sysfs can detemine namespaces. - * @namespace: Namespace of the device belongs to this class. - * @pm: The default device power management operations of this class. -@@ -396,6 +397,7 @@ struct class { - - int (*suspend)(struct device *dev, pm_message_t state); - int (*resume)(struct device *dev); -+ int (*shutdown)(struct device *dev); - - const struct kobj_ns_type_operations *ns_type; - const void *(*namespace)(struct device *dev); -diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h -index 2a6b9947aaa3..743b34f56f2b 100644 ---- a/include/linux/list_lru.h -+++ b/include/linux/list_lru.h -@@ -44,6 +44,7 @@ struct list_lru_node { - /* for cgroup aware lrus points to per cgroup lists, otherwise NULL */ - struct list_lru_memcg *memcg_lrus; - #endif -+ long nr_items; - } ____cacheline_aligned_in_smp; - - struct list_lru { -diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h -index 6275d651f76e..b8a8d4239e85 100644 ---- a/include/net/ip6_route.h -+++ b/include/net/ip6_route.h -@@ -21,6 +21,7 @@ struct route_info { - #include - #include - #include -+#include - #include - #include - #include -@@ -208,4 +209,11 @@ static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, - return daddr; - } - -+static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b) -+{ -+ return a->dst.dev == b->dst.dev && -+ a->rt6i_idev == b->rt6i_idev && -+ ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && -+ !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); -+} - #endif -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index 2cbfba78d3db..863e24f1e62e 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -754,6 +754,11 @@ static int check_xadd(struct verifier_env *env, struct bpf_insn *insn) - if (err) - return err; - -+ if (is_pointer_value(env, insn->src_reg)) { -+ verbose("R%d leaks addr into mem\n", insn->src_reg); -+ return -EACCES; -+ } -+ - /* check whether atomic_add can read the memory */ - err = check_mem_access(env, insn->dst_reg, insn->off, - BPF_SIZE(insn->code), BPF_READ, -1); -diff --git a/kernel/extable.c b/kernel/extable.c -index e820ccee9846..4f06fc34313f 100644 ---- a/kernel/extable.c -+++ b/kernel/extable.c -@@ -66,7 +66,7 @@ static inline int init_kernel_text(unsigned long addr) - return 0; - } - --int core_kernel_text(unsigned long addr) -+int notrace core_kernel_text(unsigned long addr) - { - if (addr >= (unsigned long)_stext && - addr < (unsigned long)_etext) -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index 20253dbc8610..c436426a80dd 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -6123,6 +6123,9 @@ enum s_alloc { - * Build an iteration mask that can exclude certain CPUs from the upwards - * domain traversal. - * -+ * Only CPUs that can arrive at this group should be considered to continue -+ * balancing. -+ * - * Asymmetric node setups can result in situations where the domain tree is of - * unequal depth, make sure to skip domains that already cover the entire - * range. -@@ -6134,18 +6137,31 @@ enum s_alloc { - */ - static void build_group_mask(struct sched_domain *sd, struct sched_group *sg) - { -- const struct cpumask *span = sched_domain_span(sd); -+ const struct cpumask *sg_span = sched_group_cpus(sg); - struct sd_data *sdd = sd->private; - struct sched_domain *sibling; - int i; - -- for_each_cpu(i, span) { -+ for_each_cpu(i, sg_span) { - sibling = *per_cpu_ptr(sdd->sd, i); -- if (!cpumask_test_cpu(i, sched_domain_span(sibling))) -+ -+ /* -+ * Can happen in the asymmetric case, where these siblings are -+ * unused. The mask will not be empty because those CPUs that -+ * do have the top domain _should_ span the domain. -+ */ -+ if (!sibling->child) -+ continue; -+ -+ /* If we would not end up here, we can't continue from here */ -+ if (!cpumask_equal(sg_span, sched_domain_span(sibling->child))) - continue; - - cpumask_set_cpu(i, sched_group_mask(sg)); - } -+ -+ /* We must not have empty masks here */ -+ WARN_ON_ONCE(cpumask_empty(sched_group_mask(sg))); - } - - /* -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index 4c21c0b7dc91..c83d59913d78 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -1660,7 +1660,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags, - TRACE_FLAG_IRQS_NOSUPPORT | - #endif - ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) | -- ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) | -+ ((pc & SOFTIRQ_OFFSET) ? TRACE_FLAG_SOFTIRQ : 0) | - (tif_need_resched() ? TRACE_FLAG_NEED_RESCHED : 0) | - (test_preempt_need_resched() ? TRACE_FLAG_PREEMPT_RESCHED : 0); - } -diff --git a/mm/list_lru.c b/mm/list_lru.c -index 5d8dffd5b57c..786176b1a0ee 100644 ---- a/mm/list_lru.c -+++ b/mm/list_lru.c -@@ -117,6 +117,7 @@ bool list_lru_add(struct list_lru *lru, struct list_head *item) - l = list_lru_from_kmem(nlru, item); - list_add_tail(item, &l->list); - l->nr_items++; -+ nlru->nr_items++; - spin_unlock(&nlru->lock); - return true; - } -@@ -136,6 +137,7 @@ bool list_lru_del(struct list_lru *lru, struct list_head *item) - l = list_lru_from_kmem(nlru, item); - list_del_init(item); - l->nr_items--; -+ nlru->nr_items--; - spin_unlock(&nlru->lock); - return true; - } -@@ -183,15 +185,10 @@ EXPORT_SYMBOL_GPL(list_lru_count_one); - - unsigned long list_lru_count_node(struct list_lru *lru, int nid) - { -- long count = 0; -- int memcg_idx; -+ struct list_lru_node *nlru; - -- count += __list_lru_count_one(lru, nid, -1); -- if (list_lru_memcg_aware(lru)) { -- for_each_memcg_cache_index(memcg_idx) -- count += __list_lru_count_one(lru, nid, memcg_idx); -- } -- return count; -+ nlru = &lru->node[nid]; -+ return nlru->nr_items; - } - EXPORT_SYMBOL_GPL(list_lru_count_node); - -@@ -226,6 +223,7 @@ restart: - assert_spin_locked(&nlru->lock); - case LRU_REMOVED: - isolated++; -+ nlru->nr_items--; - /* - * If the lru lock has been dropped, our list - * traversal is now invalid and so we have to -diff --git a/mm/mmap.c b/mm/mmap.c -index 0990f8bc0fbe..eaa460ddcaf9 100644 ---- a/mm/mmap.c -+++ b/mm/mmap.c -@@ -2176,7 +2176,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) - - /* Guard against exceeding limits of the address space. */ - address &= PAGE_MASK; -- if (address >= TASK_SIZE) -+ if (address >= (TASK_SIZE & PAGE_MASK)) - return -ENOMEM; - address += PAGE_SIZE; - -diff --git a/net/core/dev.c b/net/core/dev.c -index 524d8b28e690..dc5d3d546150 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -4375,6 +4375,12 @@ struct packet_offload *gro_find_complete_by_type(__be16 type) - } - EXPORT_SYMBOL(gro_find_complete_by_type); - -+static void napi_skb_free_stolen_head(struct sk_buff *skb) -+{ -+ skb_dst_drop(skb); -+ kmem_cache_free(skbuff_head_cache, skb); -+} -+ - static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) - { - switch (ret) { -@@ -4388,12 +4394,10 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb) - break; - - case GRO_MERGED_FREE: -- if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) { -- skb_dst_drop(skb); -- kmem_cache_free(skbuff_head_cache, skb); -- } else { -+ if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) -+ napi_skb_free_stolen_head(skb); -+ else - __kfree_skb(skb); -- } - break; - - case GRO_HELD: -@@ -4459,10 +4463,16 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, - break; - - case GRO_DROP: -- case GRO_MERGED_FREE: - napi_reuse_skb(napi, skb); - break; - -+ case GRO_MERGED_FREE: -+ if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) -+ napi_skb_free_stolen_head(skb); -+ else -+ napi_reuse_skb(napi, skb); -+ break; -+ - case GRO_MERGED: - break; - } -@@ -7052,8 +7062,8 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, - } else { - netdev_stats_to_stats64(storage, &dev->stats); - } -- storage->rx_dropped += atomic_long_read(&dev->rx_dropped); -- storage->tx_dropped += atomic_long_read(&dev->tx_dropped); -+ storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped); -+ storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped); - return storage; - } - EXPORT_SYMBOL(dev_get_stats); -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 4bd8678329d6..0870a86e9d96 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -2263,6 +2263,8 @@ int tcp_disconnect(struct sock *sk, int flags) - tcp_init_send_head(sk); - memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); - __sk_dst_reset(sk); -+ dst_release(sk->sk_rx_dst); -+ sk->sk_rx_dst = NULL; - tcp_saved_syn_free(tp); - - WARN_ON(inet->inet_num && !icsk->icsk_bind_hash); -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 03dadbf6cc5e..735b22b1b4ea 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -1772,17 +1772,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add - - static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) - { -- if (ifp->flags&IFA_F_PERMANENT) { -- spin_lock_bh(&ifp->lock); -- addrconf_del_dad_work(ifp); -- ifp->flags |= IFA_F_TENTATIVE; -- if (dad_failed) -- ifp->flags |= IFA_F_DADFAILED; -- spin_unlock_bh(&ifp->lock); -- if (dad_failed) -- ipv6_ifa_notify(0, ifp); -- in6_ifa_put(ifp); -- } else if (ifp->flags&IFA_F_TEMPORARY) { -+ if (ifp->flags&IFA_F_TEMPORARY) { - struct inet6_ifaddr *ifpub; - spin_lock_bh(&ifp->lock); - ifpub = ifp->ifpub; -@@ -1795,6 +1785,16 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) - spin_unlock_bh(&ifp->lock); - } - ipv6_del_addr(ifp); -+ } else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) { -+ spin_lock_bh(&ifp->lock); -+ addrconf_del_dad_work(ifp); -+ ifp->flags |= IFA_F_TENTATIVE; -+ if (dad_failed) -+ ifp->flags |= IFA_F_DADFAILED; -+ spin_unlock_bh(&ifp->lock); -+ if (dad_failed) -+ ipv6_ifa_notify(0, ifp); -+ in6_ifa_put(ifp); - } else { - ipv6_del_addr(ifp); - } -@@ -3143,6 +3143,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, - { - struct net_device *dev = netdev_notifier_info_to_dev(ptr); - struct inet6_dev *idev = __in6_dev_get(dev); -+ struct net *net = dev_net(dev); - int run_pending = 0; - int err; - -@@ -3158,7 +3159,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, - case NETDEV_CHANGEMTU: - /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */ - if (dev->mtu < IPV6_MIN_MTU) { -- addrconf_ifdown(dev, 1); -+ addrconf_ifdown(dev, dev != net->loopback_dev); - break; - } - -@@ -3271,7 +3272,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, - * IPV6_MIN_MTU stop IPv6 on this interface. - */ - if (dev->mtu < IPV6_MIN_MTU) -- addrconf_ifdown(dev, 1); -+ addrconf_ifdown(dev, dev != net->loopback_dev); - } - break; - -diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c -index 1ac06723f0d7..f60e8caea767 100644 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -767,10 +767,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - goto next_iter; - } - -- if (iter->dst.dev == rt->dst.dev && -- iter->rt6i_idev == rt->rt6i_idev && -- ipv6_addr_equal(&iter->rt6i_gateway, -- &rt->rt6i_gateway)) { -+ if (rt6_duplicate_nexthop(iter, rt)) { - if (rt->rt6i_nsiblings) - rt->rt6i_nsiblings = 0; - if (!(iter->rt6i_flags & RTF_EXPIRES)) -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 8f4177a1d4f5..ef335070e98a 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -2833,17 +2833,11 @@ static int ip6_route_info_append(struct list_head *rt6_nh_list, - struct rt6_info *rt, struct fib6_config *r_cfg) - { - struct rt6_nh *nh; -- struct rt6_info *rtnh; - int err = -EEXIST; - - list_for_each_entry(nh, rt6_nh_list, next) { - /* check if rt6_info already exists */ -- rtnh = nh->rt6_info; -- -- if (rtnh->dst.dev == rt->dst.dev && -- rtnh->rt6i_idev == rt->rt6i_idev && -- ipv6_addr_equal(&rtnh->rt6i_gateway, -- &rt->rt6i_gateway)) -+ if (rt6_duplicate_nexthop(nh->rt6_info, rt)) - return err; - } - -diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c -index 0936a4a32b47..e353e3255206 100644 ---- a/net/rds/tcp_listen.c -+++ b/net/rds/tcp_listen.c -@@ -78,7 +78,7 @@ int rds_tcp_accept_one(struct socket *sock) - struct inet_sock *inet; - struct rds_tcp_connection *rs_tcp; - -- ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, -+ ret = sock_create_lite(sock->sk->sk_family, - sock->sk->sk_type, sock->sk->sk_protocol, - &new_sock); - if (ret) -diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c -index 95b560f0b253..6d340cd6e2a7 100644 ---- a/net/sched/sch_api.c -+++ b/net/sched/sch_api.c -@@ -1004,6 +1004,9 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, - - return sch; - } -+ /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */ -+ if (ops->destroy) -+ ops->destroy(sch); - err_out3: - dev_put(dev); - kfree((char *) sch - sch->padded); -diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c -index 13d6f83ec491..45d4b2f22f62 100644 ---- a/net/sched/sch_hhf.c -+++ b/net/sched/sch_hhf.c -@@ -636,7 +636,9 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) - q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN * - sizeof(u32)); - if (!q->hhf_arrays[i]) { -- hhf_destroy(sch); -+ /* Note: hhf_destroy() will be called -+ * by our caller. -+ */ - return -ENOMEM; - } - } -@@ -647,7 +649,9 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt) - q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN / - BITS_PER_BYTE); - if (!q->hhf_valid_bits[i]) { -- hhf_destroy(sch); -+ /* Note: hhf_destroy() will be called -+ * by our caller. -+ */ - return -ENOMEM; - } - } -diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c -index 3e82f047caaf..d9c84328e7eb 100644 ---- a/net/sched/sch_mq.c -+++ b/net/sched/sch_mq.c -@@ -52,7 +52,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) - /* pre-allocate qdiscs, attachment can't fail */ - priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), - GFP_KERNEL); -- if (priv->qdiscs == NULL) -+ if (!priv->qdiscs) - return -ENOMEM; - - for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { -@@ -60,18 +60,14 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) - qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops, - TC_H_MAKE(TC_H_MAJ(sch->handle), - TC_H_MIN(ntx + 1))); -- if (qdisc == NULL) -- goto err; -+ if (!qdisc) -+ return -ENOMEM; - priv->qdiscs[ntx] = qdisc; - qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; - } - - sch->flags |= TCQ_F_MQROOT; - return 0; -- --err: -- mq_destroy(sch); -- return -ENOMEM; - } - - static void mq_attach(struct Qdisc *sch) -diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c -index ad70ecf57ce7..66bccc5ff4ea 100644 ---- a/net/sched/sch_mqprio.c -+++ b/net/sched/sch_mqprio.c -@@ -117,20 +117,17 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) - /* pre-allocate qdisc, attachment can't fail */ - priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), - GFP_KERNEL); -- if (priv->qdiscs == NULL) { -- err = -ENOMEM; -- goto err; -- } -+ if (!priv->qdiscs) -+ return -ENOMEM; - - for (i = 0; i < dev->num_tx_queues; i++) { - dev_queue = netdev_get_tx_queue(dev, i); - qdisc = qdisc_create_dflt(dev_queue, default_qdisc_ops, - TC_H_MAKE(TC_H_MAJ(sch->handle), - TC_H_MIN(i + 1))); -- if (qdisc == NULL) { -- err = -ENOMEM; -- goto err; -- } -+ if (!qdisc) -+ return -ENOMEM; -+ - priv->qdiscs[i] = qdisc; - qdisc->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT; - } -@@ -143,7 +140,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) - priv->hw_owned = 1; - err = dev->netdev_ops->ndo_setup_tc(dev, qopt->num_tc); - if (err) -- goto err; -+ return err; - } else { - netdev_set_num_tc(dev, qopt->num_tc); - for (i = 0; i < qopt->num_tc; i++) -@@ -157,10 +154,6 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) - - sch->flags |= TCQ_F_MQROOT; - return 0; -- --err: -- mqprio_destroy(sch); -- return err; - } - - static void mqprio_attach(struct Qdisc *sch) -diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c -index 498f0a2cb47f..4431e2833e45 100644 ---- a/net/sched/sch_sfq.c -+++ b/net/sched/sch_sfq.c -@@ -742,9 +742,10 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) - q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor); - q->slots = sfq_alloc(sizeof(q->slots[0]) * q->maxflows); - if (!q->ht || !q->slots) { -- sfq_destroy(sch); -+ /* Note: sfq_destroy() will be called by our caller */ - return -ENOMEM; - } -+ - for (i = 0; i < q->divisor; i++) - q->ht[i] = SFQ_EMPTY_SLOT; - -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 9d0953e5734f..de10e3c0e2a4 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -302,8 +302,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { - [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, - [NL80211_ATTR_PID] = { .type = NLA_U32 }, - [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, -- [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, -- .len = WLAN_PMKID_LEN }, -+ [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, - [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, - [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, - [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, -@@ -359,6 +358,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { - [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, - [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, - [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, -+ [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, - [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, - [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, - [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, -@@ -5705,6 +5705,10 @@ static int validate_scan_freqs(struct nlattr *freqs) - struct nlattr *attr1, *attr2; - int n_channels = 0, tmp1, tmp2; - -+ nla_for_each_nested(attr1, freqs, tmp1) -+ if (nla_len(attr1) != sizeof(u32)) -+ return 0; -+ - nla_for_each_nested(attr1, freqs, tmp1) { - n_channels++; - /* -diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl -index 2b3c22808c3b..6ac6550d751c 100755 ---- a/scripts/checkpatch.pl -+++ b/scripts/checkpatch.pl -@@ -3252,7 +3252,7 @@ sub process { - $fixedline =~ s/\s*=\s*$/ = {/; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $line; -- $fixedline =~ s/^(.\s*){\s*/$1/; -+ $fixedline =~ s/^(.\s*)\{\s*/$1/; - fix_insert_line($fixlinenr, $fixedline); - } - } -@@ -3602,7 +3602,7 @@ sub process { - my $fixedline = rtrim($prevrawline) . " {"; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $rawline; -- $fixedline =~ s/^(.\s*){\s*/$1\t/; -+ $fixedline =~ s/^(.\s*)\{\s*/$1\t/; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } -@@ -4091,7 +4091,7 @@ sub process { - if (ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr) && - $fix) { -- $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/; -+ $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/; - } - } - -diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h -index c808c7d02d21..e69118b2077e 100644 ---- a/tools/lib/lockdep/uinclude/linux/lockdep.h -+++ b/tools/lib/lockdep/uinclude/linux/lockdep.h -@@ -8,7 +8,7 @@ - #include - #include - --#define MAX_LOCK_DEPTH 2000UL -+#define MAX_LOCK_DEPTH 255UL - - #define asmlinkage - #define __visible -diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c -index 10a21a958aaf..763f37fecfb8 100644 ---- a/tools/testing/selftests/capabilities/test_execve.c -+++ b/tools/testing/selftests/capabilities/test_execve.c -@@ -138,9 +138,6 @@ static void chdir_to_tmpfs(void) - - if (chdir(cwd) != 0) - err(1, "chdir to private tmpfs"); -- -- if (umount2(".", MNT_DETACH) != 0) -- err(1, "detach private tmpfs"); - } - - static void copy_fromat_to(int fromfd, const char *fromname, const char *toname) -@@ -248,7 +245,7 @@ static int do_tests(int uid, const char *our_path) - err(1, "chown"); - if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0) - err(1, "chmod"); --} -+ } - - capng_get_caps_process(); - -@@ -384,7 +381,7 @@ static int do_tests(int uid, const char *our_path) - } else { - printf("[RUN]\tNon-root +ia, sgidnonroot => i\n"); - exec_other_validate_cap("./validate_cap_sgidnonroot", -- false, false, true, false); -+ false, false, true, false); - - if (fork_wait()) { - printf("[RUN]\tNon-root +ia, sgidroot => i\n"); diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.78-79.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.78-79.patch deleted file mode 100644 index bf34060d4..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.78-79.patch +++ /dev/null @@ -1,2607 +0,0 @@ -diff --git a/Makefile b/Makefile -index ac77ae8ee0b1..1440a94b2474 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 78 -+SUBLEVEL = 79 - EXTRAVERSION = - NAME = Blurry Fish Butt - -@@ -619,6 +619,9 @@ include arch/$(SRCARCH)/Makefile - KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) - KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,) - KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) -+KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) -+KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) -+KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) - - ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE - KBUILD_CFLAGS += -Os -diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h -index de781cf54bc7..da80878f2c0d 100644 ---- a/arch/mips/include/asm/branch.h -+++ b/arch/mips/include/asm/branch.h -@@ -74,10 +74,7 @@ static inline int compute_return_epc(struct pt_regs *regs) - return __microMIPS_compute_return_epc(regs); - if (cpu_has_mips16) - return __MIPS16e_compute_return_epc(regs); -- return regs->cp0_epc; -- } -- -- if (!delay_slot(regs)) { -+ } else if (!delay_slot(regs)) { - regs->cp0_epc += 4; - return 0; - } -diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c -index e9fed8ca9b42..71e8f4c0b8da 100644 ---- a/arch/mips/kernel/branch.c -+++ b/arch/mips/kernel/branch.c -@@ -399,7 +399,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs) - * - * @regs: Pointer to pt_regs - * @insn: branch instruction to decode -- * @returns: -EFAULT on error and forces SIGBUS, and on success -+ * @returns: -EFAULT on error and forces SIGILL, and on success - * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after - * evaluating the branch. - * -@@ -431,7 +431,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - /* Fall through */ - case jr_op: - if (NO_R6EMU && insn.r_format.func == jr_op) -- goto sigill_r6; -+ goto sigill_r2r6; - regs->cp0_epc = regs->regs[insn.r_format.rs]; - break; - } -@@ -446,7 +446,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - switch (insn.i_format.rt) { - case bltzl_op: - if (NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case bltz_op: - if ((long)regs->regs[insn.i_format.rs] < 0) { - epc = epc + 4 + (insn.i_format.simmediate << 2); -@@ -459,7 +459,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - - case bgezl_op: - if (NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case bgez_op: - if ((long)regs->regs[insn.i_format.rs] >= 0) { - epc = epc + 4 + (insn.i_format.simmediate << 2); -@@ -473,10 +473,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - case bltzal_op: - case bltzall_op: - if (NO_R6EMU && (insn.i_format.rs || -- insn.i_format.rt == bltzall_op)) { -- ret = -SIGILL; -- break; -- } -+ insn.i_format.rt == bltzall_op)) -+ goto sigill_r2r6; - regs->regs[31] = epc + 8; - /* - * OK we are here either because we hit a NAL -@@ -507,10 +505,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - case bgezal_op: - case bgezall_op: - if (NO_R6EMU && (insn.i_format.rs || -- insn.i_format.rt == bgezall_op)) { -- ret = -SIGILL; -- break; -- } -+ insn.i_format.rt == bgezall_op)) -+ goto sigill_r2r6; - regs->regs[31] = epc + 8; - /* - * OK we are here either because we hit a BAL -@@ -556,6 +552,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - /* - * These are unconditional and in j_format. - */ -+ case jalx_op: - case jal_op: - regs->regs[31] = regs->cp0_epc + 8; - case j_op: -@@ -573,7 +570,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - */ - case beql_op: - if (NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case beq_op: - if (regs->regs[insn.i_format.rs] == - regs->regs[insn.i_format.rt]) { -@@ -587,7 +584,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - - case bnel_op: - if (NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case bne_op: - if (regs->regs[insn.i_format.rs] != - regs->regs[insn.i_format.rt]) { -@@ -601,7 +598,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - - case blezl_op: /* not really i_format */ - if (!insn.i_format.rt && NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case blez_op: - /* - * Compact branches for R6 for the -@@ -636,7 +633,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - - case bgtzl_op: - if (!insn.i_format.rt && NO_R6EMU) -- goto sigill_r6; -+ goto sigill_r2r6; - case bgtz_op: - /* - * Compact branches for R6 for the -@@ -843,11 +840,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, - return ret; - - sigill_dsp: -- printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm); -- force_sig(SIGBUS, current); -+ pr_info("%s: DSP branch but not DSP ASE - sending SIGILL.\n", -+ current->comm); -+ force_sig(SIGILL, current); - return -EFAULT; --sigill_r6: -- pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n", -+sigill_r2r6: -+ pr_info("%s: R2 branch but r2-to-r6 emulator is not present - sending SIGILL.\n", - current->comm); - force_sig(SIGILL, current); - return -EFAULT; -diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c -index 298b2b773d12..f1fab6ff53e6 100644 ---- a/arch/mips/kernel/proc.c -+++ b/arch/mips/kernel/proc.c -@@ -83,7 +83,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) - } - - seq_printf(m, "isa\t\t\t:"); -- if (cpu_has_mips_r1) -+ if (cpu_has_mips_1) - seq_printf(m, " mips1"); - if (cpu_has_mips_2) - seq_printf(m, "%s", " mips2"); -diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c -index c95bf18260f8..24c115a0721a 100644 ---- a/arch/mips/kernel/ptrace.c -+++ b/arch/mips/kernel/ptrace.c -@@ -927,7 +927,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) - audit_syscall_exit(regs); - - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) -- trace_sys_exit(regs, regs->regs[2]); -+ trace_sys_exit(regs, regs_return_value(regs)); - - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); -diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S -index 2d23c834ba96..29b0c5f978e4 100644 ---- a/arch/mips/kernel/scall32-o32.S -+++ b/arch/mips/kernel/scall32-o32.S -@@ -372,7 +372,7 @@ EXPORT(sys_call_table) - PTR sys_writev - PTR sys_cacheflush - PTR sys_cachectl -- PTR sys_sysmips -+ PTR __sys_sysmips - PTR sys_ni_syscall /* 4150 */ - PTR sys_getsid - PTR sys_fdatasync -diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S -index deac63315d0e..a6323a969919 100644 ---- a/arch/mips/kernel/scall64-64.S -+++ b/arch/mips/kernel/scall64-64.S -@@ -312,7 +312,7 @@ EXPORT(sys_call_table) - PTR sys_sched_getaffinity - PTR sys_cacheflush - PTR sys_cachectl -- PTR sys_sysmips -+ PTR __sys_sysmips - PTR sys_io_setup /* 5200 */ - PTR sys_io_destroy - PTR sys_io_getevents -diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S -index ee93d5fe61d7..e0fdca8d3abe 100644 ---- a/arch/mips/kernel/scall64-n32.S -+++ b/arch/mips/kernel/scall64-n32.S -@@ -298,7 +298,7 @@ EXPORT(sysn32_call_table) - PTR compat_sys_sched_getaffinity - PTR sys_cacheflush - PTR sys_cachectl -- PTR sys_sysmips -+ PTR __sys_sysmips - PTR compat_sys_io_setup /* 6200 */ - PTR sys_io_destroy - PTR compat_sys_io_getevents -diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S -index b77052ec6fb2..87c697181d25 100644 ---- a/arch/mips/kernel/scall64-o32.S -+++ b/arch/mips/kernel/scall64-o32.S -@@ -367,7 +367,7 @@ EXPORT(sys32_call_table) - PTR compat_sys_writev - PTR sys_cacheflush - PTR sys_cachectl -- PTR sys_sysmips -+ PTR __sys_sysmips - PTR sys_ni_syscall /* 4150 */ - PTR sys_getsid - PTR sys_fdatasync -diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c -index 53a7ef9a8f32..4234b2d726c5 100644 ---- a/arch/mips/kernel/syscall.c -+++ b/arch/mips/kernel/syscall.c -@@ -28,6 +28,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -138,10 +139,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) - __asm__ __volatile__ ( - " .set "MIPS_ISA_ARCH_LEVEL" \n" - " li %[err], 0 \n" -- "1: ll %[old], (%[addr]) \n" -+ "1: \n" -+ user_ll("%[old]", "(%[addr])") - " move %[tmp], %[new] \n" -- "2: sc %[tmp], (%[addr]) \n" -- " bnez %[tmp], 4f \n" -+ "2: \n" -+ user_sc("%[tmp]", "(%[addr])") -+ " beqz %[tmp], 4f \n" - "3: \n" - " .insn \n" - " .subsection 2 \n" -@@ -199,6 +202,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new) - unreachable(); - } - -+/* -+ * mips_atomic_set() normally returns directly via syscall_exit potentially -+ * clobbering static registers, so be sure to preserve them. -+ */ -+save_static_function(sys_sysmips); -+ - SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2) - { - switch (cmd) { -diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c -index 734a2c7665ec..6da2e4a6ba39 100644 ---- a/arch/mips/math-emu/cp1emu.c -+++ b/arch/mips/math-emu/cp1emu.c -@@ -2496,6 +2496,35 @@ dcopuop: - return 0; - } - -+/* -+ * Emulate FPU instructions. -+ * -+ * If we use FPU hardware, then we have been typically called to handle -+ * an unimplemented operation, such as where an operand is a NaN or -+ * denormalized. In that case exit the emulation loop after a single -+ * iteration so as to let hardware execute any subsequent instructions. -+ * -+ * If we have no FPU hardware or it has been disabled, then continue -+ * emulating floating-point instructions until one of these conditions -+ * has occurred: -+ * -+ * - a non-FPU instruction has been encountered, -+ * -+ * - an attempt to emulate has ended with a signal, -+ * -+ * - the ISA mode has been switched. -+ * -+ * We need to terminate the emulation loop if we got switched to the -+ * MIPS16 mode, whether supported or not, so that we do not attempt -+ * to emulate a MIPS16 instruction as a regular MIPS FPU instruction. -+ * Similarly if we got switched to the microMIPS mode and only the -+ * regular MIPS mode is supported, so that we do not attempt to emulate -+ * a microMIPS instruction as a regular MIPS FPU instruction. Or if -+ * we got switched to the regular MIPS mode and only the microMIPS mode -+ * is supported, so that we do not attempt to emulate a regular MIPS -+ * instruction that should cause an Address Error exception instead. -+ * For simplicity we always terminate upon an ISA mode switch. -+ */ - int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, - int has_fpu, void *__user *fault_addr) - { -@@ -2581,6 +2610,15 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, - break; - if (sig) - break; -+ /* -+ * We have to check for the ISA bit explicitly here, -+ * because `get_isa16_mode' may return 0 if support -+ * for code compression has been globally disabled, -+ * or otherwise we may produce the wrong signal or -+ * even proceed successfully where we must not. -+ */ -+ if ((xcp->cp0_epc ^ prevepc) & 0x1) -+ break; - - cond_resched(); - } while (xcp->cp0_epc > prevepc); -diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h -index 55f106ed12bf..039c4b910615 100644 ---- a/arch/powerpc/include/asm/atomic.h -+++ b/arch/powerpc/include/asm/atomic.h -@@ -460,7 +460,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) - * Atomically increments @v by 1, so long as @v is non-zero. - * Returns non-zero if @v was non-zero, and zero otherwise. - */ --static __inline__ long atomic64_inc_not_zero(atomic64_t *v) -+static __inline__ int atomic64_inc_not_zero(atomic64_t *v) - { - long t1, t2; - -@@ -479,7 +479,7 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v) - : "r" (&v->counter) - : "cc", "xer", "memory"); - -- return t1; -+ return t1 != 0; - } - - #endif /* __powerpc64__ */ -diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h -index 627d129d7fcb..ca372bbc0ffe 100644 ---- a/arch/powerpc/include/asm/reg.h -+++ b/arch/powerpc/include/asm/reg.h -@@ -1236,7 +1236,7 @@ static inline unsigned long mfvtb (void) - " .llong 0\n" \ - ".previous" \ - : "=r" (rval) \ -- : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL)); \ -+ : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \ - rval;}) - #else - #define mftb() ({unsigned long rval; \ -diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c -index 4014881e9843..e37162d356d8 100644 ---- a/arch/powerpc/lib/sstep.c -+++ b/arch/powerpc/lib/sstep.c -@@ -687,8 +687,10 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, - case 19: - switch ((instr >> 1) & 0x3ff) { - case 0: /* mcrf */ -- rd = (instr >> 21) & 0x1c; -- ra = (instr >> 16) & 0x1c; -+ rd = 7 - ((instr >> 23) & 0x7); -+ ra = 7 - ((instr >> 18) & 0x7); -+ rd *= 4; -+ ra *= 4; - val = (regs->ccr >> ra) & 0xf; - regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd); - goto instr_done; -@@ -967,6 +969,19 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs, - #endif - - case 19: /* mfcr */ -+ if ((instr >> 20) & 1) { -+ imm = 0xf0000000UL; -+ for (sh = 0; sh < 8; ++sh) { -+ if (instr & (0x80000 >> sh)) { -+ regs->gpr[rd] = regs->ccr & imm; -+ break; -+ } -+ imm >>= 4; -+ } -+ -+ goto instr_done; -+ } -+ - regs->gpr[rd] = regs->ccr; - regs->gpr[rd] &= 0xffffffffUL; - goto instr_done; -diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h -index 6ba0bf928909..6bc941be6921 100644 ---- a/arch/s390/include/asm/syscall.h -+++ b/arch/s390/include/asm/syscall.h -@@ -64,6 +64,12 @@ static inline void syscall_get_arguments(struct task_struct *task, - { - unsigned long mask = -1UL; - -+ /* -+ * No arguments for this syscall, there's nothing to do. -+ */ -+ if (!n) -+ return; -+ - BUG_ON(i + n > 6); - #ifdef CONFIG_COMPAT - if (test_tsk_thread_flag(task, TIF_31BIT)) -diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h -index 4c20dd333412..85133b2b8e99 100644 ---- a/arch/x86/include/asm/xen/hypercall.h -+++ b/arch/x86/include/asm/xen/hypercall.h -@@ -43,6 +43,7 @@ - - #include - #include -+#include - - #include - #include -@@ -213,10 +214,12 @@ privcmd_call(unsigned call, - __HYPERCALL_DECLS; - __HYPERCALL_5ARG(a1, a2, a3, a4, a5); - -+ stac(); - asm volatile("call *%[call]" - : __HYPERCALL_5PARAM - : [call] "a" (&hypercall_page[call]) - : __HYPERCALL_CLOBBER5); -+ clac(); - - return (long)__res; - } -diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c -index e75907601a41..1e5eb9f2ff5f 100644 ---- a/arch/x86/kernel/acpi/boot.c -+++ b/arch/x86/kernel/acpi/boot.c -@@ -329,6 +329,14 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, - struct mpc_intsrc mp_irq; - - /* -+ * Check bus_irq boundary. -+ */ -+ if (bus_irq >= NR_IRQS_LEGACY) { -+ pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq); -+ return; -+ } -+ -+ /* - * Convert 'gsi' to 'ioapic.pin'. - */ - ioapic = mp_find_ioapic(gsi); -diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c -index 1e5d2f07416b..fc91c98bee01 100644 ---- a/arch/x86/kernel/apic/io_apic.c -+++ b/arch/x86/kernel/apic/io_apic.c -@@ -2115,7 +2115,7 @@ static inline void __init check_timer(void) - int idx; - idx = find_irq_entry(apic1, pin1, mp_INT); - if (idx != -1 && irq_trigger(idx)) -- unmask_ioapic_irq(irq_get_chip_data(0)); -+ unmask_ioapic_irq(irq_get_irq_data(0)); - } - irq_domain_deactivate_irq(irq_data); - irq_domain_activate_irq(irq_data); -diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c -index a48824deabc5..3f94e5fc110a 100644 ---- a/drivers/base/power/domain.c -+++ b/drivers/base/power/domain.c -@@ -1373,7 +1373,7 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain); - int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *subdomain) - { -- struct gpd_link *link; -+ struct gpd_link *l, *link; - int ret = -EINVAL; - - if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) -@@ -1388,7 +1388,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - goto out; - } - -- list_for_each_entry(link, &genpd->master_links, master_node) { -+ list_for_each_entry_safe(link, l, &genpd->master_links, master_node) { - if (link->slave != subdomain) - continue; - -@@ -1642,10 +1642,10 @@ EXPORT_SYMBOL_GPL(__of_genpd_add_provider); - */ - void of_genpd_del_provider(struct device_node *np) - { -- struct of_genpd_provider *cp; -+ struct of_genpd_provider *cp, *tmp; - - mutex_lock(&of_genpd_mutex); -- list_for_each_entry(cp, &of_genpd_providers, link) { -+ list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) { - if (cp->node == np) { - list_del(&cp->link); - of_node_put(cp->node); -diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c -index a084a4751fa9..25372dc381d4 100644 ---- a/drivers/char/ipmi/ipmi_msghandler.c -+++ b/drivers/char/ipmi/ipmi_msghandler.c -@@ -3877,6 +3877,9 @@ static void smi_recv_tasklet(unsigned long val) - * because the lower layer is allowed to hold locks while calling - * message delivery. - */ -+ -+ rcu_read_lock(); -+ - if (!run_to_completion) - spin_lock_irqsave(&intf->xmit_msgs_lock, flags); - if (intf->curr_msg == NULL && !intf->in_shutdown) { -@@ -3899,6 +3902,8 @@ static void smi_recv_tasklet(unsigned long val) - if (newmsg) - intf->handlers->sender(intf->send_info, newmsg); - -+ rcu_read_unlock(); -+ - handle_new_recv_msgs(intf); - } - -diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c -index 0d83cfb9708f..f53e8ba2c718 100644 ---- a/drivers/char/ipmi/ipmi_ssif.c -+++ b/drivers/char/ipmi/ipmi_ssif.c -@@ -758,6 +758,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, - result, len, data[2]); - } else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 - || data[1] != IPMI_GET_MSG_FLAGS_CMD) { -+ /* -+ * Don't abort here, maybe it was a queued -+ * response to a previous command. -+ */ -+ ipmi_ssif_unlock_cond(ssif_info, flags); - pr_warn(PFX "Invalid response getting flags: %x %x\n", - data[0], data[1]); - } else { -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -index 475c38fe9245..e40a6d8b0b92 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -@@ -1126,6 +1126,9 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, - if (size & 0x3 || *pos & 0x3) - return -EINVAL; - -+ if (*pos >= adev->mc.mc_vram_size) -+ return -ENXIO; -+ - while (size) { - unsigned long flags; - uint32_t value; -diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c -index a3b96d691ac9..58bf94b69186 100644 ---- a/drivers/gpu/drm/drm_dp_mst_topology.c -+++ b/drivers/gpu/drm/drm_dp_mst_topology.c -@@ -330,6 +330,13 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg, - return false; - } - -+ /* -+ * ignore out-of-order messages or messages that are part of a -+ * failed transaction -+ */ -+ if (!recv_hdr.somt && !msg->have_somt) -+ return false; -+ - /* get length contained in this portion */ - msg->curchunk_len = recv_hdr.msg_len; - msg->curchunk_hdrlen = hdrlen; -@@ -2163,7 +2170,7 @@ out_unlock: - } - EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); - --static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) -+static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) - { - int len; - u8 replyblock[32]; -@@ -2178,12 +2185,12 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) - replyblock, len); - if (ret != len) { - DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret); -- return; -+ return false; - } - ret = drm_dp_sideband_msg_build(msg, replyblock, len, true); - if (!ret) { - DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]); -- return; -+ return false; - } - replylen = msg->curchunk_len + msg->curchunk_hdrlen; - -@@ -2195,21 +2202,32 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) - ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply, - replyblock, len); - if (ret != len) { -- DRM_DEBUG_KMS("failed to read a chunk\n"); -+ DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n", -+ len, ret); -+ return false; - } -+ - ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); -- if (ret == false) -+ if (!ret) { - DRM_DEBUG_KMS("failed to build sideband msg\n"); -+ return false; -+ } -+ - curreply += len; - replylen -= len; - } -+ return true; - } - - static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) - { - int ret = 0; - -- drm_dp_get_one_sb_msg(mgr, false); -+ if (!drm_dp_get_one_sb_msg(mgr, false)) { -+ memset(&mgr->down_rep_recv, 0, -+ sizeof(struct drm_dp_sideband_msg_rx)); -+ return 0; -+ } - - if (mgr->down_rep_recv.have_eomt) { - struct drm_dp_sideband_msg_tx *txmsg; -@@ -2265,7 +2283,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) - static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) - { - int ret = 0; -- drm_dp_get_one_sb_msg(mgr, true); -+ -+ if (!drm_dp_get_one_sb_msg(mgr, true)) { -+ memset(&mgr->up_req_recv, 0, -+ sizeof(struct drm_dp_sideband_msg_rx)); -+ return 0; -+ } - - if (mgr->up_req_recv.have_eomt) { - struct drm_dp_sideband_msg_req_body msg; -@@ -2317,7 +2340,9 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) - DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); - } - -- drm_dp_put_mst_branch_device(mstb); -+ if (mstb) -+ drm_dp_put_mst_branch_device(mstb); -+ - memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); - } - return ret; -diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c -index d4ac8c837314..8e86cf7da614 100644 ---- a/drivers/gpu/drm/radeon/atombios_encoders.c -+++ b/drivers/gpu/drm/radeon/atombios_encoders.c -@@ -30,6 +30,7 @@ - #include "radeon_audio.h" - #include "atom.h" - #include -+#include - - extern int atom_debug; - -@@ -2183,9 +2184,17 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx) - goto assigned; - } - -- /* on DCE32 and encoder can driver any block so just crtc id */ -+ /* -+ * On DCE32 any encoder can drive any block so usually just use crtc id, -+ * but Apple thinks different at least on iMac10,1, so there use linkb, -+ * otherwise the internal eDP panel will stay dark. -+ */ - if (ASIC_IS_DCE32(rdev)) { -- enc_idx = radeon_crtc->crtc_id; -+ if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1")) -+ enc_idx = (dig->linkb) ? 1 : 0; -+ else -+ enc_idx = radeon_crtc->crtc_id; -+ - goto assigned; - } - -diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c -index 3c32f095a873..2ccf81168d1e 100644 ---- a/drivers/gpu/drm/radeon/ci_dpm.c -+++ b/drivers/gpu/drm/radeon/ci_dpm.c -@@ -782,6 +782,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev) - if (r600_dpm_get_vrefresh(rdev) > 120) - return true; - -+ /* disable mclk switching if the refresh is >120Hz, even if the -+ * blanking period would allow it -+ */ -+ if (r600_dpm_get_vrefresh(rdev) > 120) -+ return true; -+ - if (vblank_time < switch_limit) - return true; - else -diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c -index 3f5741a3e728..43d5166db4c6 100644 ---- a/drivers/infiniband/core/cma.c -+++ b/drivers/infiniband/core/cma.c -@@ -857,6 +857,8 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, - } else - ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, - qp_attr_mask); -+ qp_attr->port_num = id_priv->id.port_num; -+ *qp_attr_mask |= IB_QP_PORT; - } else - ret = -ENOSYS; - -diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c -index 89abfdb539ac..c84c685056b9 100644 ---- a/drivers/input/serio/i8042.c -+++ b/drivers/input/serio/i8042.c -@@ -434,8 +434,10 @@ static int i8042_start(struct serio *serio) - { - struct i8042_port *port = serio->port_data; - -+ spin_lock_irq(&i8042_lock); - port->exists = true; -- mb(); -+ spin_unlock_irq(&i8042_lock); -+ - return 0; - } - -@@ -448,16 +450,20 @@ static void i8042_stop(struct serio *serio) - { - struct i8042_port *port = serio->port_data; - -+ spin_lock_irq(&i8042_lock); - port->exists = false; -+ port->serio = NULL; -+ spin_unlock_irq(&i8042_lock); - - /* -+ * We need to make sure that interrupt handler finishes using -+ * our serio port before we return from this function. - * We synchronize with both AUX and KBD IRQs because there is - * a (very unlikely) chance that AUX IRQ is raised for KBD port - * and vice versa. - */ - synchronize_irq(I8042_AUX_IRQ); - synchronize_irq(I8042_KBD_IRQ); -- port->serio = NULL; - } - - /* -@@ -574,7 +580,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) - - spin_unlock_irqrestore(&i8042_lock, flags); - -- if (likely(port->exists && !filtered)) -+ if (likely(serio && !filtered)) - serio_interrupt(serio, data, dfl); - - out: -diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c -index d81be5e471d0..f24a9e14021d 100644 ---- a/drivers/md/raid1.c -+++ b/drivers/md/raid1.c -@@ -1088,7 +1088,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) - */ - DEFINE_WAIT(w); - for (;;) { -- flush_signals(current); -+ sigset_t full, old; - prepare_to_wait(&conf->wait_barrier, - &w, TASK_INTERRUPTIBLE); - if (bio_end_sector(bio) <= mddev->suspend_lo || -@@ -1097,7 +1097,10 @@ static void make_request(struct mddev *mddev, struct bio * bio) - !md_cluster_ops->area_resyncing(mddev, WRITE, - bio->bi_iter.bi_sector, bio_end_sector(bio)))) - break; -+ sigfillset(&full); -+ sigprocmask(SIG_BLOCK, &full, &old); - schedule(); -+ sigprocmask(SIG_SETMASK, &old, NULL); - } - finish_wait(&conf->wait_barrier, &w); - } -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 4384b46cee1a..fc182c4f2619 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -5279,12 +5279,15 @@ static void make_request(struct mddev *mddev, struct bio * bi) - * userspace, we want an interruptible - * wait. - */ -- flush_signals(current); - prepare_to_wait(&conf->wait_for_overlap, - &w, TASK_INTERRUPTIBLE); - if (logical_sector >= mddev->suspend_lo && - logical_sector < mddev->suspend_hi) { -+ sigset_t full, old; -+ sigfillset(&full); -+ sigprocmask(SIG_BLOCK, &full, &old); - schedule(); -+ sigprocmask(SIG_SETMASK, &old, NULL); - do_prepare = true; - } - goto retry; -@@ -7528,12 +7531,10 @@ static void end_reshape(struct r5conf *conf) - { - - if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { -- struct md_rdev *rdev; - - spin_lock_irq(&conf->device_lock); - conf->previous_raid_disks = conf->raid_disks; -- rdev_for_each(rdev, conf->mddev) -- rdev->data_offset = rdev->new_data_offset; -+ md_finish_reshape(conf->mddev); - smp_wmb(); - conf->reshape_progress = MaxSector; - conf->mddev->reshape_position = MaxSector; -diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c -index 8f2556ec3971..61611d1682d1 100644 ---- a/drivers/media/pci/cx88/cx88-cards.c -+++ b/drivers/media/pci/cx88/cx88-cards.c -@@ -3691,7 +3691,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) - core->nr = nr; - sprintf(core->name, "cx88[%d]", core->nr); - -- core->tvnorm = V4L2_STD_NTSC_M; -+ /* -+ * Note: Setting initial standard here would cause first call to -+ * cx88_set_tvnorm() to return without programming any registers. Leave -+ * it blank for at this point and it will get set later in -+ * cx8800_initdev() -+ */ -+ core->tvnorm = 0; -+ - core->width = 320; - core->height = 240; - core->field = V4L2_FIELD_INTERLACED; -diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c -index aef9acf351f6..abbf5b05b6f5 100644 ---- a/drivers/media/pci/cx88/cx88-video.c -+++ b/drivers/media/pci/cx88/cx88-video.c -@@ -1429,7 +1429,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, - - /* initial device configuration */ - mutex_lock(&core->lock); -- cx88_set_tvnorm(core, core->tvnorm); -+ cx88_set_tvnorm(core, V4L2_STD_NTSC_M); - v4l2_ctrl_handler_setup(&core->video_hdl); - v4l2_ctrl_handler_setup(&core->audio_hdl); - cx88_video_mux(core, 0); -diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c -index 4a608cbe0fdb..9c6fc09b88e0 100644 ---- a/drivers/media/platform/s5p-jpeg/jpeg-core.c -+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c -@@ -1098,10 +1098,10 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, - struct s5p_jpeg_ctx *ctx) - { - int c, components = 0, notfound, n_dht = 0, n_dqt = 0; -- unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0, -- sof_len = 0; -- unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER], -- dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; -+ unsigned int height = 0, width = 0, word, subsampling = 0; -+ unsigned int sos = 0, sof = 0, sof_len = 0; -+ unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER]; -+ unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER]; - long length; - struct s5p_jpeg_buffer jpeg_buffer; - -diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c -index 65f80b8b9f7a..eb9e7feb9b13 100644 ---- a/drivers/media/rc/imon.c -+++ b/drivers/media/rc/imon.c -@@ -1629,7 +1629,7 @@ static void imon_incoming_packet(struct imon_context *ictx, - if (kc == KEY_KEYBOARD && !ictx->release_code) { - ictx->last_keycode = kc; - if (!nomouse) { -- ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; -+ ictx->pad_mouse = !ictx->pad_mouse; - dev_dbg(dev, "toggling to %s mode\n", - ictx->pad_mouse ? "mouse" : "keyboard"); - spin_unlock_irqrestore(&ictx->kc_lock, flags); -diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c -index 65fed7146e9b..cc91f7b3d90c 100644 ---- a/drivers/misc/enclosure.c -+++ b/drivers/misc/enclosure.c -@@ -375,6 +375,7 @@ int enclosure_add_device(struct enclosure_device *edev, int component, - struct device *dev) - { - struct enclosure_component *cdev; -+ int err; - - if (!edev || component >= edev->components) - return -EINVAL; -@@ -384,12 +385,17 @@ int enclosure_add_device(struct enclosure_device *edev, int component, - if (cdev->dev == dev) - return -EEXIST; - -- if (cdev->dev) -+ if (cdev->dev) { - enclosure_remove_links(cdev); -- -- put_device(cdev->dev); -+ put_device(cdev->dev); -+ } - cdev->dev = get_device(dev); -- return enclosure_add_links(cdev); -+ err = enclosure_add_links(cdev); -+ if (err) { -+ put_device(cdev->dev); -+ cdev->dev = NULL; -+ } -+ return err; - } - EXPORT_SYMBOL_GPL(enclosure_add_device); - -diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -index 201425e7f9cb..fbc8c9a9014b 100644 ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -1815,8 +1815,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) - static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) - { - REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); -- REG_SET_BIT(ah, 0x9864, 0x7f000); -- REG_SET_BIT(ah, 0x9924, 0x7f00fe); - REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - REG_WRITE(ah, AR_CR, AR_CR_RXD); - REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); -diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c -index ac4781f37e78..b4e6304afd40 100644 ---- a/drivers/net/wireless/ath/ath9k/tx99.c -+++ b/drivers/net/wireless/ath/ath9k/tx99.c -@@ -190,22 +190,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, - if (strtobool(buf, &start)) - return -EINVAL; - -+ mutex_lock(&sc->mutex); -+ - if (start == sc->tx99_state) { - if (!start) -- return count; -+ goto out; - ath_dbg(common, XMIT, "Resetting TX99\n"); - ath9k_tx99_deinit(sc); - } - - if (!start) { - ath9k_tx99_deinit(sc); -- return count; -+ goto out; - } - - r = ath9k_tx99_init(sc); -- if (r) -+ if (r) { -+ mutex_unlock(&sc->mutex); - return r; -- -+ } -+out: -+ mutex_unlock(&sc->mutex); - return count; - } - -diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c -index 44f059f7f34e..9ebe00ea8f81 100644 ---- a/drivers/net/wireless/ti/wlcore/spi.c -+++ b/drivers/net/wireless/ti/wlcore/spi.c -@@ -71,7 +71,7 @@ - * only support SPI for 12xx - this code should be reworked when 18xx - * support is introduced - */ --#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) -+#define SPI_AGGR_BUFFER_SIZE (4 * SZ_4K) - - /* Maximum number of SPI write chunks */ - #define WSPI_MAX_NUM_OF_CHUNKS \ -diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c -index f8dcdf4b24f6..af62c4c854f3 100644 ---- a/drivers/nfc/nfcmrvl/fw_dnld.c -+++ b/drivers/nfc/nfcmrvl/fw_dnld.c -@@ -459,7 +459,7 @@ int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv) - - INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work); - snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq", -- dev_name(priv->dev)); -+ dev_name(&priv->ndev->nfc_dev->dev)); - priv->fw_dnld.rx_wq = create_singlethread_workqueue(name); - if (!priv->fw_dnld.rx_wq) - return -ENOMEM; -@@ -496,6 +496,7 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name) - { - struct nfcmrvl_private *priv = nci_get_drvdata(ndev); - struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld; -+ int res; - - if (!priv->support_fw_dnld) - return -ENOTSUPP; -@@ -511,7 +512,9 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name) - */ - - /* Retrieve FW binary */ -- if (request_firmware(&fw_dnld->fw, firmware_name, priv->dev) < 0) { -+ res = request_firmware(&fw_dnld->fw, firmware_name, -+ &ndev->nfc_dev->dev); -+ if (res < 0) { - nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name); - return -ENOENT; - } -diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c -index 51c8240a1672..a446590a71ca 100644 ---- a/drivers/nfc/nfcmrvl/main.c -+++ b/drivers/nfc/nfcmrvl/main.c -@@ -124,12 +124,13 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, - memcpy(&priv->config, pdata, sizeof(*pdata)); - - if (priv->config.reset_n_io) { -- rc = devm_gpio_request_one(dev, -- priv->config.reset_n_io, -- GPIOF_OUT_INIT_LOW, -- "nfcmrvl_reset_n"); -- if (rc < 0) -+ rc = gpio_request_one(priv->config.reset_n_io, -+ GPIOF_OUT_INIT_LOW, -+ "nfcmrvl_reset_n"); -+ if (rc < 0) { -+ priv->config.reset_n_io = 0; - nfc_err(dev, "failed to request reset_n io\n"); -+ } - } - - if (phy == NFCMRVL_PHY_SPI) { -@@ -154,7 +155,13 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, - if (!priv->ndev) { - nfc_err(dev, "nci_allocate_device failed\n"); - rc = -ENOMEM; -- goto error; -+ goto error_free_gpio; -+ } -+ -+ rc = nfcmrvl_fw_dnld_init(priv); -+ if (rc) { -+ nfc_err(dev, "failed to initialize FW download %d\n", rc); -+ goto error_free_dev; - } - - nci_set_drvdata(priv->ndev, priv); -@@ -162,24 +169,22 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy, - rc = nci_register_device(priv->ndev); - if (rc) { - nfc_err(dev, "nci_register_device failed %d\n", rc); -- goto error_free_dev; -+ goto error_fw_dnld_deinit; - } - - /* Ensure that controller is powered off */ - nfcmrvl_chip_halt(priv); - -- rc = nfcmrvl_fw_dnld_init(priv); -- if (rc) { -- nfc_err(dev, "failed to initialize FW download %d\n", rc); -- goto error_free_dev; -- } -- - nfc_info(dev, "registered with nci successfully\n"); - return priv; - -+error_fw_dnld_deinit: -+ nfcmrvl_fw_dnld_deinit(priv); - error_free_dev: - nci_free_device(priv->ndev); --error: -+error_free_gpio: -+ if (priv->config.reset_n_io) -+ gpio_free(priv->config.reset_n_io); - kfree(priv); - return ERR_PTR(rc); - } -@@ -195,7 +200,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) - nfcmrvl_fw_dnld_deinit(priv); - - if (priv->config.reset_n_io) -- devm_gpio_free(priv->dev, priv->config.reset_n_io); -+ gpio_free(priv->config.reset_n_io); - - nci_unregister_device(ndev); - nci_free_device(ndev); -diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c -index 83a99e38e7bd..6c0c301611c4 100644 ---- a/drivers/nfc/nfcmrvl/uart.c -+++ b/drivers/nfc/nfcmrvl/uart.c -@@ -109,6 +109,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) - struct nfcmrvl_private *priv; - struct nfcmrvl_platform_data *pdata = NULL; - struct nfcmrvl_platform_data config; -+ struct device *dev = nu->tty->dev; - - /* - * Platform data cannot be used here since usually it is already used -@@ -116,9 +117,8 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) - * and check if DT entries were added. - */ - -- if (nu->tty->dev->parent && nu->tty->dev->parent->of_node) -- if (nfcmrvl_uart_parse_dt(nu->tty->dev->parent->of_node, -- &config) == 0) -+ if (dev && dev->parent && dev->parent->of_node) -+ if (nfcmrvl_uart_parse_dt(dev->parent->of_node, &config) == 0) - pdata = &config; - - if (!pdata) { -@@ -131,7 +131,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu) - } - - priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_UART, nu, &uart_ops, -- nu->tty->dev, pdata); -+ dev, pdata); - if (IS_ERR(priv)) - return PTR_ERR(priv); - -diff --git a/drivers/of/device.c b/drivers/of/device.c -index e5f47cec75f3..97a280d50d6d 100644 ---- a/drivers/of/device.c -+++ b/drivers/of/device.c -@@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) - - return tsize; - } -+EXPORT_SYMBOL_GPL(of_device_get_modalias); - - /** - * of_device_uevent - Display OF related uevent information -@@ -287,3 +288,4 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) - - return 0; - } -+EXPORT_SYMBOL_GPL(of_device_uevent_modalias); -diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c -index d7ffd66814bb..fca925543fae 100644 ---- a/drivers/pci/pci-driver.c -+++ b/drivers/pci/pci-driver.c -@@ -945,6 +945,7 @@ static int pci_pm_thaw_noirq(struct device *dev) - return pci_legacy_resume_early(dev); - - pci_update_current_state(pci_dev, PCI_D0); -+ pci_restore_state(pci_dev); - - if (drv && drv->pm && drv->pm->thaw_noirq) - error = drv->pm->thaw_noirq(dev); -diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c -index 6b3da1bb0d63..2db681722d2c 100644 ---- a/drivers/spmi/spmi.c -+++ b/drivers/spmi/spmi.c -@@ -364,11 +364,23 @@ static int spmi_drv_remove(struct device *dev) - return 0; - } - -+static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) -+{ -+ int ret; -+ -+ ret = of_device_uevent_modalias(dev, env); -+ if (ret != -ENODEV) -+ return ret; -+ -+ return 0; -+} -+ - static struct bus_type spmi_bus_type = { - .name = "spmi", - .match = spmi_device_match, - .probe = spmi_drv_probe, - .remove = spmi_drv_remove, -+ .uevent = spmi_drv_uevent, - }; - - /** -diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c -index 82a7c27c517f..02c3feef4e36 100644 ---- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c -+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c -@@ -47,6 +47,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { - {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ - {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ - {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ -+ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ - {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ - {} /* Terminating entry */ - }; -diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c -index dc1bd1f1bdfe..634ad3662ed6 100644 ---- a/drivers/target/iscsi/iscsi_target_configfs.c -+++ b/drivers/target/iscsi/iscsi_target_configfs.c -@@ -868,6 +868,7 @@ DEF_TPG_ATTRIB(default_erl); - DEF_TPG_ATTRIB(t10_pi); - DEF_TPG_ATTRIB(fabric_prot_type); - DEF_TPG_ATTRIB(tpg_enabled_sendtargets); -+DEF_TPG_ATTRIB(login_keys_workaround); - - static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { - &iscsi_tpg_attrib_attr_authentication, -@@ -883,6 +884,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { - &iscsi_tpg_attrib_attr_t10_pi, - &iscsi_tpg_attrib_attr_fabric_prot_type, - &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets, -+ &iscsi_tpg_attrib_attr_login_keys_workaround, - NULL, - }; - -diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c -index 9fc9117d0f22..549a2bbbf4df 100644 ---- a/drivers/target/iscsi/iscsi_target_nego.c -+++ b/drivers/target/iscsi/iscsi_target_nego.c -@@ -818,7 +818,8 @@ static int iscsi_target_handle_csg_zero( - SENDER_TARGET, - login->rsp_buf, - &login->rsp_length, -- conn->param_list); -+ conn->param_list, -+ conn->tpg->tpg_attrib.login_keys_workaround); - if (ret < 0) - return -1; - -@@ -888,7 +889,8 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log - SENDER_TARGET, - login->rsp_buf, - &login->rsp_length, -- conn->param_list); -+ conn->param_list, -+ conn->tpg->tpg_attrib.login_keys_workaround); - if (ret < 0) { - iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, - ISCSI_LOGIN_STATUS_INIT_ERR); -diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c -index 6d1b0acbc5b3..76bde76edad1 100644 ---- a/drivers/target/iscsi/iscsi_target_parameters.c -+++ b/drivers/target/iscsi/iscsi_target_parameters.c -@@ -764,7 +764,8 @@ static int iscsi_check_for_auth_key(char *key) - return 0; - } - --static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) -+static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param, -+ bool keys_workaround) - { - if (IS_TYPE_BOOL_AND(param)) { - if (!strcmp(param->value, NO)) -@@ -772,19 +773,31 @@ static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param) - } else if (IS_TYPE_BOOL_OR(param)) { - if (!strcmp(param->value, YES)) - SET_PSTATE_REPLY_OPTIONAL(param); -- /* -- * Required for gPXE iSCSI boot client -- */ -- if (!strcmp(param->name, IMMEDIATEDATA)) -- SET_PSTATE_REPLY_OPTIONAL(param); -+ -+ if (keys_workaround) { -+ /* -+ * Required for gPXE iSCSI boot client -+ */ -+ if (!strcmp(param->name, IMMEDIATEDATA)) -+ SET_PSTATE_REPLY_OPTIONAL(param); -+ } - } else if (IS_TYPE_NUMBER(param)) { - if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) - SET_PSTATE_REPLY_OPTIONAL(param); -- /* -- * Required for gPXE iSCSI boot client -- */ -- if (!strcmp(param->name, MAXCONNECTIONS)) -- SET_PSTATE_REPLY_OPTIONAL(param); -+ -+ if (keys_workaround) { -+ /* -+ * Required for Mellanox Flexboot PXE boot ROM -+ */ -+ if (!strcmp(param->name, FIRSTBURSTLENGTH)) -+ SET_PSTATE_REPLY_OPTIONAL(param); -+ -+ /* -+ * Required for gPXE iSCSI boot client -+ */ -+ if (!strcmp(param->name, MAXCONNECTIONS)) -+ SET_PSTATE_REPLY_OPTIONAL(param); -+ } - } else if (IS_PHASE_DECLARATIVE(param)) - SET_PSTATE_REPLY_OPTIONAL(param); - } -@@ -1421,7 +1434,8 @@ int iscsi_encode_text_output( - u8 sender, - char *textbuf, - u32 *length, -- struct iscsi_param_list *param_list) -+ struct iscsi_param_list *param_list, -+ bool keys_workaround) - { - char *output_buf = NULL; - struct iscsi_extra_response *er; -@@ -1457,7 +1471,8 @@ int iscsi_encode_text_output( - *length += 1; - output_buf = textbuf + *length; - SET_PSTATE_PROPOSER(param); -- iscsi_check_proposer_for_optional_reply(param); -+ iscsi_check_proposer_for_optional_reply(param, -+ keys_workaround); - pr_debug("Sending key: %s=%s\n", - param->name, param->value); - } -diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h -index a0751e3f0813..17a58c2913f2 100644 ---- a/drivers/target/iscsi/iscsi_target_parameters.h -+++ b/drivers/target/iscsi/iscsi_target_parameters.h -@@ -40,7 +40,7 @@ extern int iscsi_extract_key_value(char *, char **, char **); - extern int iscsi_update_param_value(struct iscsi_param *, char *); - extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *); - extern int iscsi_encode_text_output(u8, u8, char *, u32 *, -- struct iscsi_param_list *); -+ struct iscsi_param_list *, bool); - extern int iscsi_check_negotiated_keys(struct iscsi_param_list *); - extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *, - struct iscsi_param_list *); -diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c -index 205a509b0dfb..63e1dcc5914d 100644 ---- a/drivers/target/iscsi/iscsi_target_tpg.c -+++ b/drivers/target/iscsi/iscsi_target_tpg.c -@@ -227,6 +227,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg) - a->t10_pi = TA_DEFAULT_T10_PI; - a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE; - a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS; -+ a->login_keys_workaround = TA_DEFAULT_LOGIN_KEYS_WORKAROUND; - } - - int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg) -@@ -899,3 +900,21 @@ int iscsit_ta_tpg_enabled_sendtargets( - - return 0; - } -+ -+int iscsit_ta_login_keys_workaround( -+ struct iscsi_portal_group *tpg, -+ u32 flag) -+{ -+ struct iscsi_tpg_attrib *a = &tpg->tpg_attrib; -+ -+ if ((flag != 0) && (flag != 1)) { -+ pr_err("Illegal value %d\n", flag); -+ return -EINVAL; -+ } -+ -+ a->login_keys_workaround = flag; -+ pr_debug("iSCSI_TPG[%hu] - TPG enabled bit for login keys workaround: %s ", -+ tpg->tpgt, (a->login_keys_workaround) ? "ON" : "OFF"); -+ -+ return 0; -+} -diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h -index 2da211920c18..901a712180f0 100644 ---- a/drivers/target/iscsi/iscsi_target_tpg.h -+++ b/drivers/target/iscsi/iscsi_target_tpg.h -@@ -39,5 +39,6 @@ extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32); - extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32); - extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32); - extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32); -+extern int iscsit_ta_login_keys_workaround(struct iscsi_portal_group *, u32); - - #endif /* ISCSI_TARGET_TPG_H */ -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index 37c77db6e737..f71bedea973a 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -728,6 +728,15 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) - if (cmd->transport_state & CMD_T_ABORTED || - cmd->transport_state & CMD_T_STOP) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); -+ /* -+ * If COMPARE_AND_WRITE was stopped by __transport_wait_for_tasks(), -+ * release se_device->caw_sem obtained by sbc_compare_and_write() -+ * since target_complete_ok_work() or target_complete_failure_work() -+ * won't be called to invoke the normal CAW completion callbacks. -+ */ -+ if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) { -+ up(&dev->caw_sem); -+ } - complete_all(&cmd->t_transport_stop_comp); - return; - } else if (!success) { -diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c -index 5b4b47ed948b..87d87ac1c8a0 100644 ---- a/drivers/thermal/cpu_cooling.c -+++ b/drivers/thermal/cpu_cooling.c -@@ -191,8 +191,10 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) - mutex_lock(&cooling_list_lock); - list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { - if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) { -+ unsigned long level = get_level(cpufreq_dev, freq); -+ - mutex_unlock(&cooling_list_lock); -- return get_level(cpufreq_dev, freq); -+ return level; - } - } - mutex_unlock(&cooling_list_lock); -diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c -index 0b7194086c5a..df96f5f88c15 100644 ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -1759,6 +1759,9 @@ static const struct usb_device_id acm_ids[] = { - { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ - .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ - }, -+ { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ -+ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ -+ }, - - { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ - .driver_info = CLEAR_HALT_CONDITIONS, -diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c -index e9675e8f0e54..a8a2d5005e6e 100644 ---- a/drivers/usb/host/xhci-hub.c -+++ b/drivers/usb/host/xhci-hub.c -@@ -768,6 +768,9 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, - clear_bit(wIndex, &bus_state->resuming_ports); - - set_bit(wIndex, &bus_state->rexit_ports); -+ -+ xhci_test_and_clear_bit(xhci, port_array, wIndex, -+ PORT_PLC); - xhci_set_link_state(xhci, port_array, wIndex, - XDEV_U0); - -diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c -index de7dce6eb474..ece0787d62bf 100644 ---- a/drivers/usb/host/xhci-ring.c -+++ b/drivers/usb/host/xhci-ring.c -@@ -856,13 +856,16 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, - (ep->ep_state & EP_GETTING_NO_STREAMS)) { - int stream_id; - -- for (stream_id = 0; stream_id < ep->stream_info->num_streams; -+ for (stream_id = 1; stream_id < ep->stream_info->num_streams; - stream_id++) { -+ ring = ep->stream_info->stream_rings[stream_id]; -+ if (!ring) -+ continue; -+ - xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, - "Killing URBs for slot ID %u, ep index %u, stream %u", -- slot_id, ep_index, stream_id + 1); -- xhci_kill_ring_urbs(xhci, -- ep->stream_info->stream_rings[stream_id]); -+ slot_id, ep_index, stream_id); -+ xhci_kill_ring_urbs(xhci, ring); - } - } else { - ring = ep->ring; -diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c -index d82fa36c3465..005da0866836 100644 ---- a/drivers/usb/renesas_usbhs/common.c -+++ b/drivers/usb/renesas_usbhs/common.c -@@ -733,8 +733,10 @@ static int usbhsc_resume(struct device *dev) - struct usbhs_priv *priv = dev_get_drvdata(dev); - struct platform_device *pdev = usbhs_priv_to_pdev(priv); - -- if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) -+ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { - usbhsc_power_ctrl(priv, 1); -+ usbhs_mod_autonomy_mode(priv); -+ } - - usbhs_platform_call(priv, phy_reset, pdev); - -diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c -index efc4fae123a4..8647d2c2a8c4 100644 ---- a/drivers/usb/renesas_usbhs/mod_gadget.c -+++ b/drivers/usb/renesas_usbhs/mod_gadget.c -@@ -37,6 +37,7 @@ struct usbhsg_gpriv; - struct usbhsg_uep { - struct usb_ep ep; - struct usbhs_pipe *pipe; -+ spinlock_t lock; /* protect the pipe */ - - char ep_name[EP_NAME_SIZE]; - -@@ -638,10 +639,16 @@ usbhsg_ep_enable_end: - static int usbhsg_ep_disable(struct usb_ep *ep) - { - struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); -- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); -+ struct usbhs_pipe *pipe; -+ unsigned long flags; -+ int ret = 0; - -- if (!pipe) -- return -EINVAL; -+ spin_lock_irqsave(&uep->lock, flags); -+ pipe = usbhsg_uep_to_pipe(uep); -+ if (!pipe) { -+ ret = -EINVAL; -+ goto out; -+ } - - usbhsg_pipe_disable(uep); - usbhs_pipe_free(pipe); -@@ -649,6 +656,9 @@ static int usbhsg_ep_disable(struct usb_ep *ep) - uep->pipe->mod_private = NULL; - uep->pipe = NULL; - -+out: -+ spin_unlock_irqrestore(&uep->lock, flags); -+ - return 0; - } - -@@ -698,8 +708,11 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) - { - struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); - struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); -- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); -+ struct usbhs_pipe *pipe; -+ unsigned long flags; - -+ spin_lock_irqsave(&uep->lock, flags); -+ pipe = usbhsg_uep_to_pipe(uep); - if (pipe) - usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); - -@@ -708,6 +721,7 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) - * even if the pipe is NULL. - */ - usbhsg_queue_pop(uep, ureq, -ECONNRESET); -+ spin_unlock_irqrestore(&uep->lock, flags); - - return 0; - } -@@ -854,10 +868,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) - { - struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); - struct usbhs_mod *mod = usbhs_mod_get_current(priv); -- struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); -+ struct usbhsg_uep *uep; - struct device *dev = usbhs_priv_to_dev(priv); - unsigned long flags; -- int ret = 0; -+ int ret = 0, i; - - /******************** spin lock ********************/ - usbhs_lock(priv, flags); -@@ -889,7 +903,9 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) - usbhs_sys_set_test_mode(priv, 0); - usbhs_sys_function_ctrl(priv, 0); - -- usbhsg_ep_disable(&dcp->ep); -+ /* disable all eps */ -+ usbhsg_for_each_uep_with_dcp(uep, gpriv, i) -+ usbhsg_ep_disable(&uep->ep); - - dev_dbg(dev, "stop gadget\n"); - -@@ -1072,6 +1088,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) - ret = -ENOMEM; - goto usbhs_mod_gadget_probe_err_gpriv; - } -+ spin_lock_init(&uep->lock); - - gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); - dev_info(dev, "%stransceiver found\n", -diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c -index 39afd7045c43..7bb5f8da5357 100644 ---- a/drivers/usb/storage/isd200.c -+++ b/drivers/usb/storage/isd200.c -@@ -1520,8 +1520,11 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) - - /* Make sure driver was initialized */ - -- if (us->extra == NULL) -+ if (us->extra == NULL) { - usb_stor_dbg(us, "ERROR Driver not initialized\n"); -+ srb->result = DID_ERROR << 16; -+ return; -+ } - - scsi_set_resid(srb, 0); - /* scsi_bufflen might change in protocol translation to ata */ -diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c -index 6070b793cbcb..1e01e28f40f3 100644 ---- a/drivers/vfio/vfio.c -+++ b/drivers/vfio/vfio.c -@@ -296,6 +296,34 @@ static void vfio_group_put(struct vfio_group *group) - kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); - } - -+struct vfio_group_put_work { -+ struct work_struct work; -+ struct vfio_group *group; -+}; -+ -+static void vfio_group_put_bg(struct work_struct *work) -+{ -+ struct vfio_group_put_work *do_work; -+ -+ do_work = container_of(work, struct vfio_group_put_work, work); -+ -+ vfio_group_put(do_work->group); -+ kfree(do_work); -+} -+ -+static void vfio_group_schedule_put(struct vfio_group *group) -+{ -+ struct vfio_group_put_work *do_work; -+ -+ do_work = kmalloc(sizeof(*do_work), GFP_KERNEL); -+ if (WARN_ON(!do_work)) -+ return; -+ -+ INIT_WORK(&do_work->work, vfio_group_put_bg); -+ do_work->group = group; -+ schedule_work(&do_work->work); -+} -+ - /* Assume group_lock or group reference is held */ - static void vfio_group_get(struct vfio_group *group) - { -@@ -620,7 +648,14 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, - break; - } - -- vfio_group_put(group); -+ /* -+ * If we're the last reference to the group, the group will be -+ * released, which includes unregistering the iommu group notifier. -+ * We hold a read-lock on that notifier list, unregistering needs -+ * a write-lock... deadlock. Release our reference asynchronously -+ * to avoid that situation. -+ */ -+ vfio_group_schedule_put(group); - return NOTIFY_OK; - } - -@@ -1552,6 +1587,15 @@ void vfio_group_put_external_user(struct vfio_group *group) - } - EXPORT_SYMBOL_GPL(vfio_group_put_external_user); - -+bool vfio_external_group_match_file(struct vfio_group *test_group, -+ struct file *filep) -+{ -+ struct vfio_group *group = filep->private_data; -+ -+ return (filep->f_op == &vfio_group_fops) && (group == test_group); -+} -+EXPORT_SYMBOL_GPL(vfio_external_group_match_file); -+ - int vfio_external_user_iommu_id(struct vfio_group *group) - { - return iommu_group_id(group->iommu_group); -diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c -index 9314b4ea2375..be7d187d53fd 100644 ---- a/fs/ceph/dir.c -+++ b/fs/ceph/dir.c -@@ -247,6 +247,11 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx, - if (ret < 0) - err = ret; - dput(last); -+ /* last_name no longer match cache index */ -+ if (fi->readdir_cache_idx >= 0) { -+ fi->readdir_cache_idx = -1; -+ fi->dir_release_count = 0; -+ } - } - return err; - } -diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c -index e9a8d676c6bc..83dcf7bfd7b8 100644 ---- a/fs/f2fs/acl.c -+++ b/fs/f2fs/acl.c -@@ -213,7 +213,7 @@ static int __f2fs_set_acl(struct inode *inode, int type, - switch (type) { - case ACL_TYPE_ACCESS: - name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; -- if (acl) { -+ if (acl && !ipage) { - error = posix_acl_update_mode(inode, &inode->i_mode, &acl); - if (error) - return error; -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index 5b21b1ca2341..348e0a05bd18 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -1135,11 +1135,13 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) - /* Force a full look up iff the parent directory has changed */ - if (!nfs_is_exclusive_create(dir, flags) && - nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) { -- -- if (nfs_lookup_verify_inode(inode, flags)) { -+ error = nfs_lookup_verify_inode(inode, flags); -+ if (error) { - if (flags & LOOKUP_RCU) - return -ECHILD; -- goto out_zap_parent; -+ if (error == -ESTALE) -+ goto out_zap_parent; -+ goto out_error; - } - goto out_valid; - } -@@ -1163,8 +1165,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) - trace_nfs_lookup_revalidate_enter(dir, dentry, flags); - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); - trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error); -- if (error) -+ if (error == -ESTALE || error == -ENOENT) - goto out_bad; -+ if (error) -+ goto out_error; - if (nfs_compare_fh(NFS_FH(inode), fhandle)) - goto out_bad; - if ((error = nfs_refresh_inode(inode, fattr)) != 0) -diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c -index f714b98cfd74..668ac19af58f 100644 ---- a/fs/nfs/inode.c -+++ b/fs/nfs/inode.c -@@ -1241,9 +1241,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat - return 0; - /* Has the inode gone and changed behind our back? */ - if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) -- return -EIO; -+ return -ESTALE; - if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) -- return -EIO; -+ return -ESTALE; - - if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && - inode->i_version != fattr->change_attr) -diff --git a/fs/udf/inode.c b/fs/udf/inode.c -index 7be3166ba553..0e659d9c69a1 100644 ---- a/fs/udf/inode.c -+++ b/fs/udf/inode.c -@@ -1235,8 +1235,8 @@ int udf_setsize(struct inode *inode, loff_t newsize) - return err; - } - set_size: -- truncate_setsize(inode, newsize); - up_write(&iinfo->i_data_sem); -+ truncate_setsize(inode, newsize); - } else { - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { - down_write(&iinfo->i_data_sem); -@@ -1253,9 +1253,9 @@ set_size: - udf_get_block); - if (err) - return err; -+ truncate_setsize(inode, newsize); - down_write(&iinfo->i_data_sem); - udf_clear_extent_cache(inode); -- truncate_setsize(inode, newsize); - udf_truncate_extents(inode); - up_write(&iinfo->i_data_sem); - } -diff --git a/include/linux/vfio.h b/include/linux/vfio.h -index ddb440975382..34851bf2e2c8 100644 ---- a/include/linux/vfio.h -+++ b/include/linux/vfio.h -@@ -85,6 +85,8 @@ extern void vfio_unregister_iommu_driver( - */ - extern struct vfio_group *vfio_group_get_external_user(struct file *filep); - extern void vfio_group_put_external_user(struct vfio_group *group); -+extern bool vfio_external_group_match_file(struct vfio_group *group, -+ struct file *filep); - extern int vfio_external_user_iommu_id(struct vfio_group *group); - extern long vfio_external_check_extension(struct vfio_group *group, - unsigned long arg); -diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h -index 373d3342002b..e0efe3fcf739 100644 ---- a/include/target/iscsi/iscsi_target_core.h -+++ b/include/target/iscsi/iscsi_target_core.h -@@ -64,6 +64,14 @@ - #define TA_DEFAULT_FABRIC_PROT_TYPE 0 - /* TPG status needs to be enabled to return sendtargets discovery endpoint info */ - #define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1 -+/* -+ * Used to control the sending of keys with optional to respond state bit, -+ * as a workaround for non RFC compliant initiators,that do not propose, -+ * nor respond to specific keys required for login to complete. -+ * -+ * See iscsi_check_proposer_for_optional_reply() for more details. -+ */ -+#define TA_DEFAULT_LOGIN_KEYS_WORKAROUND 1 - - #define ISCSI_IOV_DATA_BUFFER 5 - -@@ -765,6 +773,7 @@ struct iscsi_tpg_attrib { - u8 t10_pi; - u32 fabric_prot_type; - u32 tpg_enabled_sendtargets; -+ u32 login_keys_workaround; - struct iscsi_portal_group *tpg; - }; - -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 22350b15b4e7..784ab8fe8714 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -6410,21 +6410,6 @@ static void perf_log_itrace_start(struct perf_event *event) - perf_output_end(&handle); - } - --static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs) --{ -- /* -- * Due to interrupt latency (AKA "skid"), we may enter the -- * kernel before taking an overflow, even if the PMU is only -- * counting user events. -- * To avoid leaking information to userspace, we must always -- * reject kernel samples when exclude_kernel is set. -- */ -- if (event->attr.exclude_kernel && !user_mode(regs)) -- return false; -- -- return true; --} -- - /* - * Generic event overflow handling, sampling. - */ -@@ -6472,12 +6457,6 @@ static int __perf_event_overflow(struct perf_event *event, - } - - /* -- * For security, drop the skid kernel samples if necessary. -- */ -- if (!sample_is_allowed(event, regs)) -- return ret; -- -- /* - * XXX event_limit might not quite work as expected on inherited - * events - */ -diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c -index 2c3a23d77704..6fcc367ad531 100644 ---- a/kernel/time/alarmtimer.c -+++ b/kernel/time/alarmtimer.c -@@ -616,7 +616,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, - * Rate limit to the tick as a hot fix to prevent DOS. Will be - * mopped up later. - */ -- if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) -+ if (timr->it.alarm.interval.tv64 && -+ ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) - timr->it.alarm.interval = ktime_set(0, TICK_NSEC); - - exp = timespec_to_ktime(new_setting->it_value); -diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index 34b2a0d5cf1a..eba904bae48c 100644 ---- a/kernel/trace/ftrace.c -+++ b/kernel/trace/ftrace.c -@@ -3535,7 +3535,7 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod) - int exclude_mod = 0; - int found = 0; - int ret; -- int clear_filter; -+ int clear_filter = 0; - - if (func) { - func_g.type = filter_parse_regex(func, len, &func_g.search, -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index c83d59913d78..d59ebd9d21df 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -6737,6 +6737,7 @@ static int instance_rmdir(const char *name) - } - kfree(tr->topts); - -+ free_cpumask_var(tr->tracing_cpumask); - kfree(tr->name); - kfree(tr); - -diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c -index 4b175df35184..906f88550cd8 100644 ---- a/net/bluetooth/smp.c -+++ b/net/bluetooth/smp.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -524,7 +525,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], - if (err) - return false; - -- return !memcmp(bdaddr->b, hash, 3); -+ return !crypto_memneq(bdaddr->b, hash, 3); - } - - int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) -@@ -577,7 +578,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) - /* This is unlikely, but we need to check that - * we didn't accidentially generate a debug key. - */ -- if (memcmp(smp->local_sk, debug_sk, 32)) -+ if (crypto_memneq(smp->local_sk, debug_sk, 32)) - break; - } - smp->debug_key = false; -@@ -991,7 +992,7 @@ static u8 smp_random(struct smp_chan *smp) - if (ret) - return SMP_UNSPECIFIED; - -- if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { -+ if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { - BT_ERR("Pairing failed (confirmation values mismatch)"); - return SMP_CONFIRM_FAILED; - } -@@ -1491,7 +1492,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) - smp->rrnd, r, cfm)) - return SMP_UNSPECIFIED; - -- if (memcmp(smp->pcnf, cfm, 16)) -+ if (crypto_memneq(smp->pcnf, cfm, 16)) - return SMP_CONFIRM_FAILED; - - smp->passkey_round++; -@@ -1875,7 +1876,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) - /* This is unlikely, but we need to check that - * we didn't accidentially generate a debug key. - */ -- if (memcmp(smp->local_sk, debug_sk, 32)) -+ if (crypto_memneq(smp->local_sk, debug_sk, 32)) - break; - } - } -@@ -2140,7 +2141,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) - if (err) - return SMP_UNSPECIFIED; - -- if (memcmp(smp->pcnf, cfm, 16)) -+ if (crypto_memneq(smp->pcnf, cfm, 16)) - return SMP_CONFIRM_FAILED; - } else { - smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), -@@ -2621,7 +2622,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) - if (err) - return SMP_UNSPECIFIED; - -- if (memcmp(cfm.confirm_val, smp->pcnf, 16)) -+ if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) - return SMP_CONFIRM_FAILED; - } - -@@ -2654,7 +2655,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) - else - hcon->pending_sec_level = BT_SECURITY_FIPS; - -- if (!memcmp(debug_pk, smp->remote_pk, 64)) -+ if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) - set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); - - if (smp->method == DSP_PASSKEY) { -@@ -2753,7 +2754,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) - if (err) - return SMP_UNSPECIFIED; - -- if (memcmp(check->e, e, 16)) -+ if (crypto_memneq(check->e, e, 16)) - return SMP_DHKEY_CHECK_FAILED; - - if (!hcon->out) { -@@ -3463,7 +3464,7 @@ static int __init test_ah(struct crypto_blkcipher *tfm_aes) - if (err) - return err; - -- if (memcmp(res, exp, 3)) -+ if (crypto_memneq(res, exp, 3)) - return -EINVAL; - - return 0; -@@ -3493,7 +3494,7 @@ static int __init test_c1(struct crypto_blkcipher *tfm_aes) - if (err) - return err; - -- if (memcmp(res, exp, 16)) -+ if (crypto_memneq(res, exp, 16)) - return -EINVAL; - - return 0; -@@ -3518,7 +3519,7 @@ static int __init test_s1(struct crypto_blkcipher *tfm_aes) - if (err) - return err; - -- if (memcmp(res, exp, 16)) -+ if (crypto_memneq(res, exp, 16)) - return -EINVAL; - - return 0; -@@ -3550,7 +3551,7 @@ static int __init test_f4(struct crypto_hash *tfm_cmac) - if (err) - return err; - -- if (memcmp(res, exp, 16)) -+ if (crypto_memneq(res, exp, 16)) - return -EINVAL; - - return 0; -@@ -3584,10 +3585,10 @@ static int __init test_f5(struct crypto_hash *tfm_cmac) - if (err) - return err; - -- if (memcmp(mackey, exp_mackey, 16)) -+ if (crypto_memneq(mackey, exp_mackey, 16)) - return -EINVAL; - -- if (memcmp(ltk, exp_ltk, 16)) -+ if (crypto_memneq(ltk, exp_ltk, 16)) - return -EINVAL; - - return 0; -@@ -3620,7 +3621,7 @@ static int __init test_f6(struct crypto_hash *tfm_cmac) - if (err) - return err; - -- if (memcmp(res, exp, 16)) -+ if (crypto_memneq(res, exp, 16)) - return -EINVAL; - - return 0; -@@ -3674,7 +3675,7 @@ static int __init test_h6(struct crypto_hash *tfm_cmac) - if (err) - return err; - -- if (memcmp(res, exp, 16)) -+ if (crypto_memneq(res, exp, 16)) - return -EINVAL; - - return 0; -diff --git a/net/key/af_key.c b/net/key/af_key.c -index e67c28e614b9..d8d95b6415e4 100644 ---- a/net/key/af_key.c -+++ b/net/key/af_key.c -@@ -65,6 +65,10 @@ struct pfkey_sock { - } dump; - }; - -+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, -+ xfrm_address_t *saddr, xfrm_address_t *daddr, -+ u16 *family); -+ - static inline struct pfkey_sock *pfkey_sk(struct sock *sk) - { - return (struct pfkey_sock *)sk; -@@ -1922,19 +1926,14 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) - - /* addresses present only in tunnel mode */ - if (t->mode == XFRM_MODE_TUNNEL) { -- u8 *sa = (u8 *) (rq + 1); -- int family, socklen; -+ int err; - -- family = pfkey_sockaddr_extract((struct sockaddr *)sa, -- &t->saddr); -- if (!family) -- return -EINVAL; -- -- socklen = pfkey_sockaddr_len(family); -- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), -- &t->id.daddr) != family) -- return -EINVAL; -- t->encap_family = family; -+ err = parse_sockaddr_pair( -+ (struct sockaddr *)(rq + 1), -+ rq->sadb_x_ipsecrequest_len - sizeof(*rq), -+ &t->saddr, &t->id.daddr, &t->encap_family); -+ if (err) -+ return err; - } else - t->encap_family = xp->family; - -@@ -1954,7 +1953,11 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) - if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy)) - return -EINVAL; - -- while (len >= sizeof(struct sadb_x_ipsecrequest)) { -+ while (len >= sizeof(*rq)) { -+ if (len < rq->sadb_x_ipsecrequest_len || -+ rq->sadb_x_ipsecrequest_len < sizeof(*rq)) -+ return -EINVAL; -+ - if ((err = parse_ipsecrequest(xp, rq)) < 0) - return err; - len -= rq->sadb_x_ipsecrequest_len; -@@ -2417,7 +2420,6 @@ out: - return err; - } - --#ifdef CONFIG_NET_KEY_MIGRATE - static int pfkey_sockaddr_pair_size(sa_family_t family) - { - return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); -@@ -2429,7 +2431,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, - { - int af, socklen; - -- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) -+ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) - return -EINVAL; - - af = pfkey_sockaddr_extract(sa, saddr); -@@ -2445,6 +2447,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, - return 0; - } - -+#ifdef CONFIG_NET_KEY_MIGRATE - static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, - struct xfrm_migrate *m) - { -@@ -2452,13 +2455,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, - struct sadb_x_ipsecrequest *rq2; - int mode; - -- if (len <= sizeof(struct sadb_x_ipsecrequest) || -- len < rq1->sadb_x_ipsecrequest_len) -+ if (len < sizeof(*rq1) || -+ len < rq1->sadb_x_ipsecrequest_len || -+ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1)) - return -EINVAL; - - /* old endoints */ - err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), -- rq1->sadb_x_ipsecrequest_len, -+ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1), - &m->old_saddr, &m->old_daddr, - &m->old_family); - if (err) -@@ -2467,13 +2471,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, - rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len); - len -= rq1->sadb_x_ipsecrequest_len; - -- if (len <= sizeof(struct sadb_x_ipsecrequest) || -- len < rq2->sadb_x_ipsecrequest_len) -+ if (len <= sizeof(*rq2) || -+ len < rq2->sadb_x_ipsecrequest_len || -+ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2)) - return -EINVAL; - - /* new endpoints */ - err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), -- rq2->sadb_x_ipsecrequest_len, -+ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2), - &m->new_saddr, &m->new_daddr, - &m->new_family); - if (err) -diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c -index 4da560005b0e..dd1649caa2b2 100644 ---- a/net/netfilter/ipvs/ip_vs_core.c -+++ b/net/netfilter/ipvs/ip_vs_core.c -@@ -845,10 +845,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, - { - unsigned int verdict = NF_DROP; - -- if (IP_VS_FWD_METHOD(cp) != 0) { -- pr_err("shouldn't reach here, because the box is on the " -- "half connection in the tun/dr module.\n"); -- } -+ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) -+ goto ignore_cp; - - /* Ensure the checksum is correct */ - if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { -@@ -882,6 +880,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, - ip_vs_notrack(skb); - else - ip_vs_update_conntrack(skb, cp, 0); -+ -+ignore_cp: - verdict = NF_ACCEPT; - - out: -@@ -1242,8 +1242,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in - */ - cp = pp->conn_out_get(ipvs, af, skb, &iph); - -- if (likely(cp)) -+ if (likely(cp)) { -+ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) -+ goto ignore_cp; - return handle_response(af, skb, pd, cp, &iph, hooknum); -+ } - if (sysctl_nat_icmp_send(ipvs) && - (pp->protocol == IPPROTO_TCP || - pp->protocol == IPPROTO_UDP || -@@ -1285,9 +1288,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in - } - } - } -+ -+out: - IP_VS_DBG_PKT(12, af, pp, skb, iph.off, - "ip_vs_out: packet continues traversal as normal"); - return NF_ACCEPT; -+ -+ignore_cp: -+ __ip_vs_conn_put(cp); -+ goto out; - } - - /* -diff --git a/net/nfc/core.c b/net/nfc/core.c -index 1fe3d3b362c0..c5a2c7e733b3 100644 ---- a/net/nfc/core.c -+++ b/net/nfc/core.c -@@ -969,6 +969,8 @@ static void nfc_release(struct device *d) - kfree(se); - } - -+ ida_simple_remove(&nfc_index_ida, dev->idx); -+ - kfree(dev); - } - -@@ -1043,6 +1045,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - int tx_headroom, int tx_tailroom) - { - struct nfc_dev *dev; -+ int rc; - - if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || - !ops->deactivate_target || !ops->im_transceive) -@@ -1055,6 +1058,15 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - if (!dev) - return NULL; - -+ rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); -+ if (rc < 0) -+ goto err_free_dev; -+ dev->idx = rc; -+ -+ dev->dev.class = &nfc_class; -+ dev_set_name(&dev->dev, "nfc%d", dev->idx); -+ device_initialize(&dev->dev); -+ - dev->ops = ops; - dev->supported_protocols = supported_protocols; - dev->tx_headroom = tx_headroom; -@@ -1077,6 +1089,11 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - } - - return dev; -+ -+err_free_dev: -+ kfree(dev); -+ -+ return ERR_PTR(rc); - } - EXPORT_SYMBOL(nfc_allocate_device); - -@@ -1091,14 +1108,6 @@ int nfc_register_device(struct nfc_dev *dev) - - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); - -- dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); -- if (dev->idx < 0) -- return dev->idx; -- -- dev->dev.class = &nfc_class; -- dev_set_name(&dev->dev, "nfc%d", dev->idx); -- device_initialize(&dev->dev); -- - mutex_lock(&nfc_devlist_mutex); - nfc_devlist_generation++; - rc = device_add(&dev->dev); -@@ -1136,12 +1145,10 @@ EXPORT_SYMBOL(nfc_register_device); - */ - void nfc_unregister_device(struct nfc_dev *dev) - { -- int rc, id; -+ int rc; - - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); - -- id = dev->idx; -- - if (dev->rfkill) { - rfkill_unregister(dev->rfkill); - rfkill_destroy(dev->rfkill); -@@ -1166,8 +1173,6 @@ void nfc_unregister_device(struct nfc_dev *dev) - nfc_devlist_generation++; - device_del(&dev->dev); - mutex_unlock(&nfc_devlist_mutex); -- -- ida_simple_remove(&nfc_index_ida, id); - } - EXPORT_SYMBOL(nfc_unregister_device); - -diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c -index ecf0a0196f18..9c222a106c7f 100644 ---- a/net/nfc/llcp_sock.c -+++ b/net/nfc/llcp_sock.c -@@ -76,7 +76,8 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) - struct sockaddr_nfc_llcp llcp_addr; - int len, ret = 0; - -- if (!addr || addr->sa_family != AF_NFC) -+ if (!addr || alen < offsetofend(struct sockaddr, sa_family) || -+ addr->sa_family != AF_NFC) - return -EINVAL; - - pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); -@@ -150,7 +151,8 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, - struct sockaddr_nfc_llcp llcp_addr; - int len, ret = 0; - -- if (!addr || addr->sa_family != AF_NFC) -+ if (!addr || alen < offsetofend(struct sockaddr, sa_family) || -+ addr->sa_family != AF_NFC) - return -EINVAL; - - pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family); -@@ -655,8 +657,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, - - pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); - -- if (!addr || len < sizeof(struct sockaddr_nfc) || -- addr->sa_family != AF_NFC) -+ if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC) - return -EINVAL; - - if (addr->service_name_len == 0 && addr->dsap == 0) -diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c -index 10c99a578421..67583ad7f610 100644 ---- a/net/nfc/nci/core.c -+++ b/net/nfc/nci/core.c -@@ -1084,8 +1084,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, - return ndev; - - free_nfc: -- kfree(ndev->nfc_dev); -- -+ nfc_free_device(ndev->nfc_dev); - free_nci: - kfree(ndev); - return NULL; -diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c -index f58c1fba1026..12dfb457275d 100644 ---- a/net/nfc/netlink.c -+++ b/net/nfc/netlink.c -@@ -873,7 +873,9 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info) - u32 device_idx, target_idx, protocol; - int rc; - -- if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) -+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || -+ !info->attrs[NFC_ATTR_TARGET_INDEX] || -+ !info->attrs[NFC_ATTR_PROTOCOLS]) - return -EINVAL; - - device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); -diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c -index bb82bb966000..c1addf49c4f2 100644 ---- a/sound/soc/soc-compress.c -+++ b/sound/soc/soc-compress.c -@@ -68,7 +68,8 @@ out: - static int soc_compr_open_fe(struct snd_compr_stream *cstream) - { - struct snd_soc_pcm_runtime *fe = cstream->private_data; -- struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; -+ struct snd_pcm_substream *fe_substream = -+ fe->pcm->streams[cstream->direction].substream; - struct snd_soc_platform *platform = fe->platform; - struct snd_soc_dpcm *dpcm; - struct snd_soc_dapm_widget_list *list; -@@ -412,7 +413,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, - struct snd_compr_params *params) - { - struct snd_soc_pcm_runtime *fe = cstream->private_data; -- struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; -+ struct snd_pcm_substream *fe_substream = -+ fe->pcm->streams[cstream->direction].substream; - struct snd_soc_platform *platform = fe->platform; - int ret = 0, stream; - -diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c -index e9703c0829f1..07b5f5951b25 100644 ---- a/tools/perf/ui/browser.c -+++ b/tools/perf/ui/browser.c -@@ -702,7 +702,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, - ui_browser__gotorc(browser, row, column + 1); - SLsmg_draw_hline(2); - -- if (row++ == 0) -+ if (++row == 0) - goto out; - } else - row = 0; -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -index 933a509a90f8..67282a759496 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -@@ -64,6 +64,25 @@ enum intel_pt_pkt_state { - INTEL_PT_STATE_FUP_NO_TIP, - }; - -+static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state) -+{ -+ switch (pkt_state) { -+ case INTEL_PT_STATE_NO_PSB: -+ case INTEL_PT_STATE_NO_IP: -+ case INTEL_PT_STATE_ERR_RESYNC: -+ case INTEL_PT_STATE_IN_SYNC: -+ case INTEL_PT_STATE_TNT: -+ return true; -+ case INTEL_PT_STATE_TIP: -+ case INTEL_PT_STATE_TIP_PGD: -+ case INTEL_PT_STATE_FUP: -+ case INTEL_PT_STATE_FUP_NO_TIP: -+ return false; -+ default: -+ return true; -+ }; -+} -+ - #ifdef INTEL_PT_STRICT - #define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB - #define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB -@@ -98,6 +117,7 @@ struct intel_pt_decoder { - uint64_t timestamp; - uint64_t tsc_timestamp; - uint64_t ref_timestamp; -+ uint64_t sample_timestamp; - uint64_t ret_addr; - uint64_t ctc_timestamp; - uint64_t ctc_delta; -@@ -140,6 +160,7 @@ struct intel_pt_decoder { - unsigned int fup_tx_flags; - unsigned int tx_flags; - uint64_t timestamp_insn_cnt; -+ uint64_t sample_insn_cnt; - uint64_t stuck_ip; - int no_progress; - int stuck_ip_prd; -@@ -896,6 +917,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, - - decoder->tot_insn_cnt += insn_cnt; - decoder->timestamp_insn_cnt += insn_cnt; -+ decoder->sample_insn_cnt += insn_cnt; - decoder->period_insn_cnt += insn_cnt; - - if (err) { -@@ -1876,6 +1898,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) - break; - - case INTEL_PT_PSB: -+ intel_pt_clear_stack(&decoder->stack); - err = intel_pt_walk_psb(decoder); - if (err) - return err; -@@ -1901,6 +1924,8 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) - { - int err; - -+ decoder->set_fup_tx_flags = false; -+ - intel_pt_log("Scanning for full IP\n"); - err = intel_pt_walk_to_ip(decoder); - if (err) -@@ -2035,7 +2060,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) - - static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder) - { -- uint64_t est = decoder->timestamp_insn_cnt << 1; -+ uint64_t est = decoder->sample_insn_cnt << 1; - - if (!decoder->cbr || !decoder->max_non_turbo_ratio) - goto out; -@@ -2043,7 +2068,7 @@ static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder) - est *= decoder->max_non_turbo_ratio; - est /= decoder->cbr; - out: -- return decoder->timestamp + est; -+ return decoder->sample_timestamp + est; - } - - const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) -@@ -2060,6 +2085,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) - break; - case INTEL_PT_STATE_NO_IP: - decoder->last_ip = 0; -+ decoder->ip = 0; - /* Fall through */ - case INTEL_PT_STATE_ERR_RESYNC: - err = intel_pt_sync_ip(decoder); -@@ -2096,15 +2122,24 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) - } - } while (err == -ENOLINK); - -- decoder->state.err = err ? intel_pt_ext_err(err) : 0; -- decoder->state.timestamp = decoder->timestamp; -+ if (err) { -+ decoder->state.err = intel_pt_ext_err(err); -+ decoder->state.from_ip = decoder->ip; -+ decoder->sample_timestamp = decoder->timestamp; -+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; -+ } else { -+ decoder->state.err = 0; -+ if (intel_pt_sample_time(decoder->pkt_state)) { -+ decoder->sample_timestamp = decoder->timestamp; -+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; -+ } -+ } -+ -+ decoder->state.timestamp = decoder->sample_timestamp; - decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); - decoder->state.cr3 = decoder->cr3; - decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; - -- if (err) -- decoder->state.from_ip = decoder->ip; -- - return &decoder->state; - } - -diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c -index 1dd087da6f31..111e09c3f4bf 100644 ---- a/virt/kvm/vfio.c -+++ b/virt/kvm/vfio.c -@@ -47,6 +47,22 @@ static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep) - return vfio_group; - } - -+static bool kvm_vfio_external_group_match_file(struct vfio_group *group, -+ struct file *filep) -+{ -+ bool ret, (*fn)(struct vfio_group *, struct file *); -+ -+ fn = symbol_get(vfio_external_group_match_file); -+ if (!fn) -+ return false; -+ -+ ret = fn(group, filep); -+ -+ symbol_put(vfio_external_group_match_file); -+ -+ return ret; -+} -+ - static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group) - { - void (*fn)(struct vfio_group *); -@@ -171,18 +187,13 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) - if (!f.file) - return -EBADF; - -- vfio_group = kvm_vfio_group_get_external_user(f.file); -- fdput(f); -- -- if (IS_ERR(vfio_group)) -- return PTR_ERR(vfio_group); -- - ret = -ENOENT; - - mutex_lock(&kv->lock); - - list_for_each_entry(kvg, &kv->group_list, node) { -- if (kvg->vfio_group != vfio_group) -+ if (!kvm_vfio_external_group_match_file(kvg->vfio_group, -+ f.file)) - continue; - - list_del(&kvg->node); -@@ -196,7 +207,7 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) - - mutex_unlock(&kv->lock); - -- kvm_vfio_group_put_external_user(vfio_group); -+ fdput(f); - - kvm_vfio_update_coherency(dev); - diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.79-80.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.79-80.patch deleted file mode 100644 index 3594fbc32..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.79-80.patch +++ /dev/null @@ -1,3287 +0,0 @@ -diff --git a/Makefile b/Makefile -index 1440a94b2474..dddd55adde24 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 79 -+SUBLEVEL = 80 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts -index 5f5e0f3d5b64..27cd4abfc74d 100644 ---- a/arch/arm/boot/dts/omap3-n900.dts -+++ b/arch/arm/boot/dts/omap3-n900.dts -@@ -697,6 +697,8 @@ - vmmc_aux-supply = <&vsim>; - bus-width = <8>; - non-removable; -+ no-sdio; -+ no-sd; - }; - - &mmc3 { -diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig -index f3142369f594..01116ee1284b 100644 ---- a/arch/arm/configs/s3c2410_defconfig -+++ b/arch/arm/configs/s3c2410_defconfig -@@ -87,9 +87,9 @@ CONFIG_IPV6_TUNNEL=m - CONFIG_NETFILTER=y - CONFIG_NF_CONNTRACK=m - CONFIG_NF_CONNTRACK_EVENTS=y --CONFIG_NF_CT_PROTO_DCCP=m --CONFIG_NF_CT_PROTO_SCTP=m --CONFIG_NF_CT_PROTO_UDPLITE=m -+CONFIG_NF_CT_PROTO_DCCP=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 -diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts -index ce5d848251fa..7b34822d61e9 100644 ---- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts -+++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts -@@ -26,7 +26,7 @@ - stdout-path = "serial0:115200n8"; - }; - -- memory { -+ memory@0 { - device_type = "memory"; - reg = <0x0 0x0 0x40000000>; - }; -diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -index 857eda5c7217..172402cc1a0f 100644 ---- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi -@@ -71,7 +71,7 @@ - <1 10 0xf01>; - }; - -- amba_apu { -+ amba_apu: amba_apu@0 { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <1>; -@@ -191,7 +191,7 @@ - }; - - i2c0: i2c@ff020000 { -- compatible = "cdns,i2c-r1p10"; -+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10"; - status = "disabled"; - interrupt-parent = <&gic>; - interrupts = <0 17 4>; -@@ -202,7 +202,7 @@ - }; - - i2c1: i2c@ff030000 { -- compatible = "cdns,i2c-r1p10"; -+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10"; - status = "disabled"; - interrupt-parent = <&gic>; - interrupts = <0 18 4>; -diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c -index 247bae758e1e..a4b466424a32 100644 ---- a/arch/arm64/mm/fault.c -+++ b/arch/arm64/mm/fault.c -@@ -66,21 +66,21 @@ void show_pte(struct mm_struct *mm, unsigned long addr) - break; - - pud = pud_offset(pgd, addr); -- printk(", *pud=%016llx", pud_val(*pud)); -+ pr_cont(", *pud=%016llx", pud_val(*pud)); - if (pud_none(*pud) || pud_bad(*pud)) - break; - - pmd = pmd_offset(pud, addr); -- printk(", *pmd=%016llx", pmd_val(*pmd)); -+ pr_cont(", *pmd=%016llx", pmd_val(*pmd)); - if (pmd_none(*pmd) || pmd_bad(*pmd)) - break; - - pte = pte_offset_map(pmd, addr); -- printk(", *pte=%016llx", pte_val(*pte)); -+ pr_cont(", *pte=%016llx", pte_val(*pte)); - pte_unmap(pte); - } while(0); - -- printk("\n"); -+ pr_cont("\n"); - } - - #ifdef CONFIG_ARM64_HW_AFDBM -diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S -index 2d69a853b742..3a08b55609b6 100644 ---- a/arch/openrisc/kernel/vmlinux.lds.S -+++ b/arch/openrisc/kernel/vmlinux.lds.S -@@ -38,6 +38,8 @@ SECTIONS - /* Read-only sections, merged into text segment: */ - . = LOAD_BASE ; - -+ _text = .; -+ - /* _s_kernel_ro must be page aligned */ - . = ALIGN(PAGE_SIZE); - _s_kernel_ro = .; -diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h -index 329771559cbb..8b3b46b7b0f2 100644 ---- a/arch/powerpc/include/asm/topology.h -+++ b/arch/powerpc/include/asm/topology.h -@@ -44,22 +44,8 @@ extern void __init dump_numa_cpu_topology(void); - extern int sysfs_add_device_to_node(struct device *dev, int nid); - extern void sysfs_remove_device_from_node(struct device *dev, int nid); - --static inline int early_cpu_to_node(int cpu) --{ -- int nid; -- -- nid = numa_cpu_lookup_table[cpu]; -- -- /* -- * Fall back to node 0 if nid is unset (it should be, except bugs). -- * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)). -- */ -- return (nid < 0) ? 0 : nid; --} - #else - --static inline int early_cpu_to_node(int cpu) { return 0; } -- - static inline void dump_numa_cpu_topology(void) {} - - static inline int sysfs_add_device_to_node(struct device *dev, int nid) -diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c -index fe6e800c1357..a20823210ac0 100644 ---- a/arch/powerpc/kernel/setup_64.c -+++ b/arch/powerpc/kernel/setup_64.c -@@ -751,7 +751,7 @@ void __init setup_arch(char **cmdline_p) - - static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) - { -- return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align, -+ return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align, - __pa(MAX_DMA_ADDRESS)); - } - -@@ -762,7 +762,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size) - - static int pcpu_cpu_distance(unsigned int from, unsigned int to) - { -- if (early_cpu_to_node(from) == early_cpu_to_node(to)) -+ if (cpu_to_node(from) == cpu_to_node(to)) - return LOCAL_DISTANCE; - else - return REMOTE_DISTANCE; -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 396dc44e783b..428563b195c3 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -2687,6 +2687,10 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) - { - int r; - int srcu_idx; -+ unsigned long ebb_regs[3] = {}; /* shut up GCC */ -+ unsigned long user_tar = 0; -+ unsigned long proc_fscr = 0; -+ unsigned int user_vrsave; - - if (!vcpu->arch.sane) { - run->exit_reason = KVM_EXIT_INTERNAL_ERROR; -@@ -2707,10 +2711,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) - run->fail_entry.hardware_entry_failure_reason = 0; - return -EINVAL; - } -+ /* Enable TM so we can read the TM SPRs */ -+ mtmsr(mfmsr() | MSR_TM); - current->thread.tm_tfhar = mfspr(SPRN_TFHAR); - current->thread.tm_tfiar = mfspr(SPRN_TFIAR); - current->thread.tm_texasr = mfspr(SPRN_TEXASR); -- current->thread.regs->msr &= ~MSR_TM; - } - #endif - -@@ -2736,6 +2741,17 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) - flush_fp_to_thread(current); - flush_altivec_to_thread(current); - flush_vsx_to_thread(current); -+ -+ /* Save userspace EBB and other register values */ -+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) { -+ ebb_regs[0] = mfspr(SPRN_EBBHR); -+ ebb_regs[1] = mfspr(SPRN_EBBRR); -+ ebb_regs[2] = mfspr(SPRN_BESCR); -+ user_tar = mfspr(SPRN_TAR); -+ proc_fscr = mfspr(SPRN_FSCR); -+ } -+ user_vrsave = mfspr(SPRN_VRSAVE); -+ - vcpu->arch.wqp = &vcpu->arch.vcore->wq; - vcpu->arch.pgdir = current->mm->pgd; - vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; -@@ -2757,6 +2773,29 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) - } - } while (is_kvmppc_resume_guest(r)); - -+ /* Restore userspace EBB and other register values */ -+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) { -+ mtspr(SPRN_EBBHR, ebb_regs[0]); -+ mtspr(SPRN_EBBRR, ebb_regs[1]); -+ mtspr(SPRN_BESCR, ebb_regs[2]); -+ mtspr(SPRN_TAR, user_tar); -+ mtspr(SPRN_FSCR, proc_fscr); -+ } -+ mtspr(SPRN_VRSAVE, user_vrsave); -+ -+ /* -+ * Since we don't do lazy TM reload, we need to reload -+ * the TM registers here. -+ */ -+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM -+ if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs && -+ (current->thread.regs->msr & MSR_TM)) { -+ mtspr(SPRN_TFHAR, current->thread.tm_tfhar); -+ mtspr(SPRN_TFIAR, current->thread.tm_tfiar); -+ mtspr(SPRN_TEXASR, current->thread.tm_texasr); -+ } -+#endif -+ - out: - vcpu->arch.state = KVMPPC_VCPU_NOTREADY; - atomic_dec(&vcpu->kvm->arch.vcpus_running); -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index 1a743f87b37d..ffab9269bfe4 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -36,6 +36,13 @@ - #define NAPPING_CEDE 1 - #define NAPPING_NOVCPU 2 - -+/* Stack frame offsets for kvmppc_hv_entry */ -+#define SFS 112 -+#define STACK_SLOT_TRAP (SFS-4) -+#define STACK_SLOT_CIABR (SFS-16) -+#define STACK_SLOT_DAWR (SFS-24) -+#define STACK_SLOT_DAWRX (SFS-32) -+ - /* - * Call kvmppc_hv_entry in real mode. - * Must be called with interrupts hard-disabled. -@@ -274,10 +281,10 @@ kvm_novcpu_exit: - bl kvmhv_accumulate_time - #endif - 13: mr r3, r12 -- stw r12, 112-4(r1) -+ stw r12, STACK_SLOT_TRAP(r1) - bl kvmhv_commence_exit - nop -- lwz r12, 112-4(r1) -+ lwz r12, STACK_SLOT_TRAP(r1) - b kvmhv_switch_to_host - - /* -@@ -489,7 +496,7 @@ kvmppc_hv_entry: - */ - mflr r0 - std r0, PPC_LR_STKOFF(r1) -- stdu r1, -112(r1) -+ stdu r1, -SFS(r1) - - /* Save R1 in the PACA */ - std r1, HSTATE_HOST_R1(r13) -@@ -643,6 +650,16 @@ kvmppc_got_guest: - mtspr SPRN_PURR,r7 - mtspr SPRN_SPURR,r8 - -+ /* Save host values of some registers */ -+BEGIN_FTR_SECTION -+ mfspr r5, SPRN_CIABR -+ mfspr r6, SPRN_DAWR -+ mfspr r7, SPRN_DAWRX -+ std r5, STACK_SLOT_CIABR(r1) -+ std r6, STACK_SLOT_DAWR(r1) -+ std r7, STACK_SLOT_DAWRX(r1) -+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) -+ - BEGIN_FTR_SECTION - /* Set partition DABR */ - /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ -@@ -1266,8 +1283,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) - */ - li r0, 0 - mtspr SPRN_IAMR, r0 -- mtspr SPRN_CIABR, r0 -- mtspr SPRN_DAWRX, r0 -+ mtspr SPRN_PSPB, r0 - mtspr SPRN_TCSCR, r0 - mtspr SPRN_WORT, r0 - /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */ -@@ -1283,6 +1299,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) - std r6,VCPU_UAMOR(r9) - li r6,0 - mtspr SPRN_AMR,r6 -+ mtspr SPRN_UAMOR, r6 - - /* Switch DSCR back to host value */ - mfspr r8, SPRN_DSCR -@@ -1424,6 +1441,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - slbia - ptesync - -+ /* Restore host values of some registers */ -+BEGIN_FTR_SECTION -+ ld r5, STACK_SLOT_CIABR(r1) -+ ld r6, STACK_SLOT_DAWR(r1) -+ ld r7, STACK_SLOT_DAWRX(r1) -+ mtspr SPRN_CIABR, r5 -+ mtspr SPRN_DAWR, r6 -+ mtspr SPRN_DAWRX, r7 -+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) -+ - /* - * POWER7/POWER8 guest -> host partition switch code. - * We don't have to lock against tlbies but we do -@@ -1533,8 +1560,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - li r0, KVM_GUEST_MODE_NONE - stb r0, HSTATE_IN_GUEST(r13) - -- ld r0, 112+PPC_LR_STKOFF(r1) -- addi r1, r1, 112 -+ ld r0, SFS+PPC_LR_STKOFF(r1) -+ addi r1, r1, SFS - mtlr r0 - blr - -diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c -index 7c7fcc042549..fb695f142563 100644 ---- a/arch/powerpc/platforms/pseries/reconfig.c -+++ b/arch/powerpc/platforms/pseries/reconfig.c -@@ -82,7 +82,6 @@ static int pSeries_reconfig_remove_node(struct device_node *np) - - of_detach_node(np); - of_node_put(parent); -- of_node_put(np); /* Must decrement the refcount */ - return 0; - } - -diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c -index 62aca448726a..2116176c1721 100644 ---- a/arch/x86/kernel/cpu/mcheck/mce_amd.c -+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c -@@ -682,6 +682,9 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) - const char *name = th_names[bank]; - int err = 0; - -+ if (!dev) -+ return -ENODEV; -+ - if (is_shared_bank(bank)) { - nb = node_to_amd_nb(amd_get_nb_id(cpu)); - -diff --git a/crypto/authencesn.c b/crypto/authencesn.c -index 0c0468869e25..52154ef21b5e 100644 ---- a/crypto/authencesn.c -+++ b/crypto/authencesn.c -@@ -245,6 +245,9 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, - u8 *ihash = ohash + crypto_ahash_digestsize(auth); - u32 tmp[2]; - -+ if (!authsize) -+ goto decrypt; -+ - /* Move high-order bits of sequence number back. */ - scatterwalk_map_and_copy(tmp, dst, 4, 4, 0); - scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0); -@@ -253,6 +256,8 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req, - if (crypto_memneq(ihash, ohash, authsize)) - return -EBADMSG; - -+decrypt: -+ - sg_init_table(areq_ctx->dst, 2); - dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen); - -diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c -index 5ea5dc219f56..73c9c7fa9001 100644 ---- a/drivers/acpi/glue.c -+++ b/drivers/acpi/glue.c -@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi_device *adev, bool check_children) - if (check_children && list_empty(&adev->children)) - return -ENODEV; - -- return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; -+ /* -+ * If the device has a _HID (or _CID) returning a valid ACPI/PNP -+ * device ID, it is better to make it look less attractive here, so that -+ * the other device with the same _ADR value (that may not have a valid -+ * device ID) can be matched going forward. [This means a second spec -+ * violation in a row, so whatever we do here is best effort anyway.] -+ */ -+ return sta_present && list_empty(&adev->pnp.ids) ? -+ FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; - } - - struct acpi_device *acpi_find_child_device(struct acpi_device *parent, -diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c -index 3f94e5fc110a..78b0ece0c867 100644 ---- a/drivers/base/power/domain.c -+++ b/drivers/base/power/domain.c -@@ -1188,7 +1188,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, - } - - dev->power.subsys_data->domain_data = &gpd_data->base; -- dev->pm_domain = &genpd->domain; - - spin_unlock_irq(&dev->power.lock); - -@@ -1207,7 +1206,6 @@ static void genpd_free_dev_data(struct device *dev, - { - spin_lock_irq(&dev->power.lock); - -- dev->pm_domain = NULL; - dev->power.subsys_data->domain_data = NULL; - - spin_unlock_irq(&dev->power.lock); -@@ -1248,6 +1246,8 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, - if (ret) - goto out; - -+ dev->pm_domain = &genpd->domain; -+ - genpd->device_count++; - genpd->max_off_time_changed = true; - -@@ -1299,6 +1299,8 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, - if (genpd->detach_dev) - genpd->detach_dev(genpd, dev); - -+ dev->pm_domain = NULL; -+ - list_del_init(&pdd->list_node); - - mutex_unlock(&genpd->lock); -diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c -index 41fb1a917b17..33e23a7a691f 100644 ---- a/drivers/block/xen-blkback/blkback.c -+++ b/drivers/block/xen-blkback/blkback.c -@@ -595,8 +595,6 @@ int xen_blkif_schedule(void *arg) - unsigned long timeout; - int ret; - -- xen_blkif_get(blkif); -- - while (!kthread_should_stop()) { - if (try_to_freeze()) - continue; -@@ -650,7 +648,6 @@ purge_gnt_list: - print_stats(blkif); - - blkif->xenblkd = NULL; -- xen_blkif_put(blkif); - - return 0; - } -diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c -index f53cff42f8da..923308201375 100644 ---- a/drivers/block/xen-blkback/xenbus.c -+++ b/drivers/block/xen-blkback/xenbus.c -@@ -221,7 +221,6 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif) - if (blkif->xenblkd) { - kthread_stop(blkif->xenblkd); - wake_up(&blkif->shutdown_wq); -- blkif->xenblkd = NULL; - } - - /* The above kthread_stop() guarantees that at this point we -@@ -266,9 +265,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif) - - static void xen_blkif_free(struct xen_blkif *blkif) - { -- -- xen_blkif_disconnect(blkif); -+ WARN_ON(xen_blkif_disconnect(blkif)); - xen_vbd_free(&blkif->vbd); -+ kfree(blkif->be->mode); -+ kfree(blkif->be); - - /* Make sure everything is drained before shutting down */ - BUG_ON(blkif->persistent_gnt_c != 0); -@@ -445,8 +445,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev) - xen_blkif_put(be->blkif); - } - -- kfree(be->mode); -- kfree(be); - return 0; - } - -diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c -index 096f0cef4da1..40d400fe5bb7 100644 ---- a/drivers/char/ipmi/ipmi_watchdog.c -+++ b/drivers/char/ipmi/ipmi_watchdog.c -@@ -1162,10 +1162,11 @@ static int wdog_reboot_handler(struct notifier_block *this, - ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); - } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { -- /* Set a long timer to let the reboot happens, but -- reboot if it hangs, but only if the watchdog -+ /* Set a long timer to let the reboot happen or -+ reset if it hangs, but only if the watchdog - timer was already running. */ -- timeout = 120; -+ if (timeout < 120) -+ timeout = 120; - pretimeout = 0; - ipmi_watchdog_state = WDOG_TIMEOUT_RESET; - ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); -diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c -index 6d56877b2e0a..a0d9ac6b6cc9 100644 ---- a/drivers/char/tpm/tpm-chip.c -+++ b/drivers/char/tpm/tpm-chip.c -@@ -29,9 +29,8 @@ - #include "tpm.h" - #include "tpm_eventlog.h" - --static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); --static LIST_HEAD(tpm_chip_list); --static DEFINE_SPINLOCK(driver_lock); -+DEFINE_IDR(dev_nums_idr); -+static DEFINE_MUTEX(idr_lock); - - struct class *tpm_class; - dev_t tpm_devt; -@@ -92,20 +91,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops); - */ - struct tpm_chip *tpm_chip_find_get(int chip_num) - { -- struct tpm_chip *pos, *chip = NULL; -+ struct tpm_chip *chip, *res = NULL; -+ int chip_prev; -+ -+ mutex_lock(&idr_lock); -+ -+ if (chip_num == TPM_ANY_NUM) { -+ chip_num = 0; -+ do { -+ chip_prev = chip_num; -+ chip = idr_get_next(&dev_nums_idr, &chip_num); -+ if (chip && !tpm_try_get_ops(chip)) { -+ res = chip; -+ break; -+ } -+ } while (chip_prev != chip_num); -+ } else { -+ chip = idr_find_slowpath(&dev_nums_idr, chip_num); -+ if (chip && !tpm_try_get_ops(chip)) -+ res = chip; -+ } - -- rcu_read_lock(); -- list_for_each_entry_rcu(pos, &tpm_chip_list, list) { -- if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) -- continue; -+ mutex_unlock(&idr_lock); - -- /* rcu prevents chip from being free'd */ -- if (!tpm_try_get_ops(pos)) -- chip = pos; -- break; -- } -- rcu_read_unlock(); -- return chip; -+ return res; - } - - /** -@@ -118,9 +127,10 @@ static void tpm_dev_release(struct device *dev) - { - struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); - -- spin_lock(&driver_lock); -- clear_bit(chip->dev_num, dev_mask); -- spin_unlock(&driver_lock); -+ mutex_lock(&idr_lock); -+ idr_remove(&dev_nums_idr, chip->dev_num); -+ mutex_unlock(&idr_lock); -+ - kfree(chip); - } - -@@ -173,6 +183,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, - const struct tpm_class_ops *ops) - { - struct tpm_chip *chip; -+ int rc; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) -@@ -180,21 +191,18 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, - - mutex_init(&chip->tpm_mutex); - init_rwsem(&chip->ops_sem); -- INIT_LIST_HEAD(&chip->list); - - chip->ops = ops; - -- spin_lock(&driver_lock); -- chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); -- spin_unlock(&driver_lock); -- -- if (chip->dev_num >= TPM_NUM_DEVICES) { -+ mutex_lock(&idr_lock); -+ rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL); -+ mutex_unlock(&idr_lock); -+ if (rc < 0) { - dev_err(dev, "No available tpm device numbers\n"); - kfree(chip); -- return ERR_PTR(-ENOMEM); -+ return ERR_PTR(rc); - } -- -- set_bit(chip->dev_num, dev_mask); -+ chip->dev_num = rc; - - scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); - -@@ -252,19 +260,28 @@ static int tpm_add_char_device(struct tpm_chip *chip) - return rc; - } - -+ /* Make the chip available. */ -+ mutex_lock(&idr_lock); -+ idr_replace(&dev_nums_idr, chip, chip->dev_num); -+ mutex_unlock(&idr_lock); -+ - return rc; - } - - static void tpm_del_char_device(struct tpm_chip *chip) - { - cdev_del(&chip->cdev); -+ device_del(&chip->dev); -+ -+ /* Make the chip unavailable. */ -+ mutex_lock(&idr_lock); -+ idr_replace(&dev_nums_idr, NULL, chip->dev_num); -+ mutex_unlock(&idr_lock); - - /* Make the driver uncallable. */ - down_write(&chip->ops_sem); - chip->ops = NULL; - up_write(&chip->ops_sem); -- -- device_del(&chip->dev); - } - - static int tpm1_chip_register(struct tpm_chip *chip) -@@ -319,11 +336,6 @@ int tpm_chip_register(struct tpm_chip *chip) - if (rc) - goto out_err; - -- /* Make the chip available. */ -- spin_lock(&driver_lock); -- list_add_tail_rcu(&chip->list, &tpm_chip_list); -- spin_unlock(&driver_lock); -- - chip->flags |= TPM_CHIP_FLAG_REGISTERED; - - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { -@@ -360,11 +372,6 @@ void tpm_chip_unregister(struct tpm_chip *chip) - if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED)) - return; - -- spin_lock(&driver_lock); -- list_del_rcu(&chip->list); -- spin_unlock(&driver_lock); -- synchronize_rcu(); -- - if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) - sysfs_remove_link(&chip->dev.parent->kobj, "ppi"); - -diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c -index 8588f2e4b9af..aaa5fa95dede 100644 ---- a/drivers/char/tpm/tpm-interface.c -+++ b/drivers/char/tpm/tpm-interface.c -@@ -1127,6 +1127,7 @@ static int __init tpm_init(void) - - static void __exit tpm_exit(void) - { -+ idr_destroy(&dev_nums_idr); - class_destroy(tpm_class); - unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); - } -diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c -index 6a4056a3f7ee..06ac6e9657d2 100644 ---- a/drivers/char/tpm/tpm-sysfs.c -+++ b/drivers/char/tpm/tpm-sysfs.c -@@ -38,6 +38,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, - - struct tpm_chip *chip = dev_get_drvdata(dev); - -+ memset(&tpm_cmd, 0, sizeof(tpm_cmd)); -+ - tpm_cmd.header.in = tpm_readpubek_header; - err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0, - "attempting to read the PUBEK"); -diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h -index e21e2c599e66..772d99b3a8e4 100644 ---- a/drivers/char/tpm/tpm.h -+++ b/drivers/char/tpm/tpm.h -@@ -34,7 +34,7 @@ - enum tpm_const { - TPM_MINOR = 224, /* officially assigned */ - TPM_BUFSIZE = 4096, -- TPM_NUM_DEVICES = 256, -+ TPM_NUM_DEVICES = 65536, - TPM_RETRY = 50, /* 5 seconds */ - }; - -@@ -200,8 +200,6 @@ struct tpm_chip { - acpi_handle acpi_dev_handle; - char ppi_version[TPM_PPI_VERSION_LEN + 1]; - #endif /* CONFIG_ACPI */ -- -- struct list_head list; - }; - - #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) -@@ -497,6 +495,7 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) - extern struct class *tpm_class; - extern dev_t tpm_devt; - extern const struct file_operations tpm_fops; -+extern struct idr dev_nums_idr; - - enum tpm_transmit_flags { - TPM_TRANSMIT_UNLOCKED = BIT(0), -diff --git a/drivers/dma/ioat/hw.h b/drivers/dma/ioat/hw.h -index 690e3b4f8202..b36da3c1073f 100644 ---- a/drivers/dma/ioat/hw.h -+++ b/drivers/dma/ioat/hw.h -@@ -64,6 +64,8 @@ - #define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e - #define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f - -+#define PCI_DEVICE_ID_INTEL_IOAT_SKX 0x2021 -+ - #define IOAT_VER_1_2 0x12 /* Version 1.2 */ - #define IOAT_VER_2_0 0x20 /* Version 2.0 */ - #define IOAT_VER_3_0 0x30 /* Version 3.0 */ -diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c -index 4ef0c5e07912..abb75ebd65ea 100644 ---- a/drivers/dma/ioat/init.c -+++ b/drivers/dma/ioat/init.c -@@ -105,6 +105,8 @@ static struct pci_device_id ioat_pci_tbl[] = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) }, - -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) }, -+ - /* I/OAT v3.3 platforms */ - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) }, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) }, -@@ -250,10 +252,15 @@ static bool is_bdx_ioat(struct pci_dev *pdev) - } - } - -+static inline bool is_skx_ioat(struct pci_dev *pdev) -+{ -+ return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false; -+} -+ - static bool is_xeon_cb32(struct pci_dev *pdev) - { - return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) || -- is_hsw_ioat(pdev) || is_bdx_ioat(pdev); -+ is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev); - } - - bool is_bwd_ioat(struct pci_dev *pdev) -@@ -1350,6 +1357,8 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) - - device->version = readb(device->reg_base + IOAT_VER_OFFSET); - if (device->version >= IOAT_VER_3_0) { -+ if (is_skx_ioat(pdev)) -+ device->version = IOAT_VER_3_2; - err = ioat3_dma_probe(device, ioat_dca_enabled); - - if (device->version >= IOAT_VER_3_3) -diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c -index a415edbe61b1..149ec2bd9bc6 100644 ---- a/drivers/dma/ti-dma-crossbar.c -+++ b/drivers/dma/ti-dma-crossbar.c -@@ -146,6 +146,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev) - match = of_match_node(ti_am335x_master_match, dma_node); - if (!match) { - dev_err(&pdev->dev, "DMA master is not supported\n"); -+ of_node_put(dma_node); - return -EINVAL; - } - -@@ -310,6 +311,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev) - match = of_match_node(ti_dra7_master_match, dma_node); - if (!match) { - dev_err(&pdev->dev, "DMA master is not supported\n"); -+ of_node_put(dma_node); - return -EINVAL; - } - -diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c -index a3b54cc76495..b66ffd44ff26 100644 ---- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c -+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c -@@ -204,7 +204,14 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - void adreno_flush(struct msm_gpu *gpu) - { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); -- uint32_t wptr = get_wptr(gpu->rb); -+ uint32_t wptr; -+ -+ /* -+ * Mask wptr value that we calculate to fit in the HW range. This is -+ * to account for the possibility that the last command fit exactly into -+ * the ringbuffer and rb->next hasn't wrapped to zero yet -+ */ -+ wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1); - - /* ensure writes to ringbuffer have hit system memory: */ - mb(); -diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c -index 1847f83b1e33..fed44d4e5b72 100644 ---- a/drivers/gpu/drm/msm/msm_gem_submit.c -+++ b/drivers/gpu/drm/msm/msm_gem_submit.c -@@ -90,7 +90,8 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, - pagefault_disable(); - } - -- if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { -+ if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) || -+ !(submit_bo.flags & MSM_SUBMIT_BO_FLAGS)) { - DRM_ERROR("invalid flags: %x\n", submit_bo.flags); - ret = -EINVAL; - goto out_unlock; -diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c -index 1f14b908b221..ae317271cf81 100644 ---- a/drivers/gpu/drm/msm/msm_ringbuffer.c -+++ b/drivers/gpu/drm/msm/msm_ringbuffer.c -@@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size) - struct msm_ringbuffer *ring; - int ret; - -- size = ALIGN(size, 4); /* size should be dword aligned */ -+ if (WARN_ON(!is_power_of_2(size))) -+ return ERR_PTR(-EINVAL); - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) { -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c -index c794b2c2d21e..6d8f21290aa2 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c -@@ -129,7 +129,7 @@ gf100_bar_init(struct nvkm_bar *base) - - if (bar->bar[0].mem) { - addr = nvkm_memory_addr(bar->bar[0].mem) >> 12; -- nvkm_wr32(device, 0x001714, 0xc0000000 | addr); -+ nvkm_wr32(device, 0x001714, 0x80000000 | addr); - } - - return 0; -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -index 48cb19949ca3..9255b9c096b6 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -@@ -282,26 +282,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) - * Page Flip - */ - --void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc, -- struct drm_file *file) --{ -- struct drm_pending_vblank_event *event; -- struct drm_device *dev = rcrtc->crtc.dev; -- unsigned long flags; -- -- /* Destroy the pending vertical blanking event associated with the -- * pending page flip, if any, and disable vertical blanking interrupts. -- */ -- spin_lock_irqsave(&dev->event_lock, flags); -- event = rcrtc->event; -- if (event && event->base.file_priv == file) { -- rcrtc->event = NULL; -- event->base.destroy(&event->base); -- drm_crtc_vblank_put(&rcrtc->crtc); -- } -- spin_unlock_irqrestore(&dev->event_lock, flags); --} -- - static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) - { - struct drm_pending_vblank_event *event; -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h -index 4b95d9d08c49..2bbe3f5aab65 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h -+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h -@@ -67,8 +67,6 @@ enum rcar_du_output { - - int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index); - void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable); --void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc, -- struct drm_file *file); - void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc); - void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); - -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c -index 40422f6b645e..bf4674aa6405 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c -@@ -144,91 +144,6 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table); - * DRM operations - */ - --static int rcar_du_unload(struct drm_device *dev) --{ -- struct rcar_du_device *rcdu = dev->dev_private; -- -- if (rcdu->fbdev) -- drm_fbdev_cma_fini(rcdu->fbdev); -- -- drm_kms_helper_poll_fini(dev); -- drm_mode_config_cleanup(dev); -- drm_vblank_cleanup(dev); -- -- dev->irq_enabled = 0; -- dev->dev_private = NULL; -- -- return 0; --} -- --static int rcar_du_load(struct drm_device *dev, unsigned long flags) --{ -- struct platform_device *pdev = dev->platformdev; -- struct device_node *np = pdev->dev.of_node; -- struct rcar_du_device *rcdu; -- struct resource *mem; -- int ret; -- -- if (np == NULL) { -- dev_err(dev->dev, "no platform data\n"); -- return -ENODEV; -- } -- -- rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); -- if (rcdu == NULL) { -- dev_err(dev->dev, "failed to allocate private data\n"); -- return -ENOMEM; -- } -- -- init_waitqueue_head(&rcdu->commit.wait); -- -- rcdu->dev = &pdev->dev; -- rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; -- rcdu->ddev = dev; -- dev->dev_private = rcdu; -- -- /* I/O resources */ -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); -- if (IS_ERR(rcdu->mmio)) -- return PTR_ERR(rcdu->mmio); -- -- /* Initialize vertical blanking interrupts handling. Start with vblank -- * disabled for all CRTCs. -- */ -- ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); -- if (ret < 0) { -- dev_err(&pdev->dev, "failed to initialize vblank\n"); -- goto done; -- } -- -- /* DRM/KMS objects */ -- ret = rcar_du_modeset_init(rcdu); -- if (ret < 0) { -- dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret); -- goto done; -- } -- -- dev->irq_enabled = 1; -- -- platform_set_drvdata(pdev, rcdu); -- --done: -- if (ret) -- rcar_du_unload(dev); -- -- return ret; --} -- --static void rcar_du_preclose(struct drm_device *dev, struct drm_file *file) --{ -- struct rcar_du_device *rcdu = dev->dev_private; -- unsigned int i; -- -- for (i = 0; i < rcdu->num_crtcs; ++i) -- rcar_du_crtc_cancel_page_flip(&rcdu->crtcs[i], file); --} -- - static void rcar_du_lastclose(struct drm_device *dev) - { - struct rcar_du_device *rcdu = dev->dev_private; -@@ -269,11 +184,7 @@ static const struct file_operations rcar_du_fops = { - static struct drm_driver rcar_du_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME - | DRIVER_ATOMIC, -- .load = rcar_du_load, -- .unload = rcar_du_unload, -- .preclose = rcar_du_preclose, - .lastclose = rcar_du_lastclose, -- .set_busid = drm_platform_set_busid, - .get_vblank_counter = drm_vblank_no_hw_counter, - .enable_vblank = rcar_du_enable_vblank, - .disable_vblank = rcar_du_disable_vblank, -@@ -333,18 +244,104 @@ static const struct dev_pm_ops rcar_du_pm_ops = { - * Platform driver - */ - --static int rcar_du_probe(struct platform_device *pdev) -+static int rcar_du_remove(struct platform_device *pdev) - { -- return drm_platform_init(&rcar_du_driver, pdev); -+ struct rcar_du_device *rcdu = platform_get_drvdata(pdev); -+ struct drm_device *ddev = rcdu->ddev; -+ -+ mutex_lock(&ddev->mode_config.mutex); -+ drm_connector_unplug_all(ddev); -+ mutex_unlock(&ddev->mode_config.mutex); -+ -+ drm_dev_unregister(ddev); -+ -+ if (rcdu->fbdev) -+ drm_fbdev_cma_fini(rcdu->fbdev); -+ -+ drm_kms_helper_poll_fini(ddev); -+ drm_mode_config_cleanup(ddev); -+ -+ drm_dev_unref(ddev); -+ -+ return 0; - } - --static int rcar_du_remove(struct platform_device *pdev) -+static int rcar_du_probe(struct platform_device *pdev) - { -- struct rcar_du_device *rcdu = platform_get_drvdata(pdev); -+ struct device_node *np = pdev->dev.of_node; -+ struct rcar_du_device *rcdu; -+ struct drm_connector *connector; -+ struct drm_device *ddev; -+ struct resource *mem; -+ int ret; -+ -+ if (np == NULL) { -+ dev_err(&pdev->dev, "no device tree node\n"); -+ return -ENODEV; -+ } -+ -+ /* Allocate and initialize the DRM and R-Car device structures. */ -+ rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); -+ if (rcdu == NULL) -+ return -ENOMEM; -+ -+ init_waitqueue_head(&rcdu->commit.wait); -+ -+ rcdu->dev = &pdev->dev; -+ rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; -+ -+ platform_set_drvdata(pdev, rcdu); - -- drm_put_dev(rcdu->ddev); -+ /* I/O resources */ -+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); -+ if (IS_ERR(rcdu->mmio)) -+ ret = PTR_ERR(rcdu->mmio); -+ -+ /* DRM/KMS objects */ -+ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); -+ if (!ddev) -+ return -ENOMEM; -+ -+ drm_dev_set_unique(ddev, dev_name(&pdev->dev)); -+ -+ rcdu->ddev = ddev; -+ ddev->dev_private = rcdu; -+ -+ ret = rcar_du_modeset_init(rcdu); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret); -+ goto error; -+ } -+ -+ ddev->irq_enabled = 1; -+ -+ /* Register the DRM device with the core and the connectors with -+ * sysfs. -+ */ -+ ret = drm_dev_register(ddev, 0); -+ if (ret) -+ goto error; -+ -+ mutex_lock(&ddev->mode_config.mutex); -+ drm_for_each_connector(connector, ddev) { -+ ret = drm_connector_register(connector); -+ if (ret < 0) -+ break; -+ } -+ mutex_unlock(&ddev->mode_config.mutex); -+ -+ if (ret < 0) -+ goto error; -+ -+ DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); - - return 0; -+ -+error: -+ rcar_du_remove(pdev); -+ -+ return ret; - } - - static struct platform_driver rcar_du_platform_driver = { -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c -index 96f2eb43713c..6038be93c58d 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c -@@ -55,12 +55,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { - .best_encoder = rcar_du_connector_best_encoder, - }; - --static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector) --{ -- drm_connector_unregister(connector); -- drm_connector_cleanup(connector); --} -- - static enum drm_connector_status - rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force) - { -@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .detect = rcar_du_hdmi_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -- .destroy = rcar_du_hdmi_connector_destroy, -+ .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - }; -@@ -108,9 +102,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, - return ret; - - drm_connector_helper_add(connector, &connector_helper_funcs); -- ret = drm_connector_register(connector); -- if (ret < 0) -- return ret; - - connector->dpms = DRM_MODE_DPMS_OFF; - drm_object_property_set_value(&connector->base, -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c -index ca12e8ca5552..46429c4be8e5 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c -@@ -761,6 +761,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) - if (ret < 0) - return ret; - -+ /* Initialize vertical blanking interrupts handling. Start with vblank -+ * disabled for all CRTCs. -+ */ -+ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); -+ if (ret < 0) -+ return ret; -+ - /* Initialize the groups. */ - num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); - -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c -index 0c43032fc693..e905f5da7aaa 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c -@@ -62,12 +62,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { - .best_encoder = rcar_du_connector_best_encoder, - }; - --static void rcar_du_lvds_connector_destroy(struct drm_connector *connector) --{ -- drm_connector_unregister(connector); -- drm_connector_cleanup(connector); --} -- - static enum drm_connector_status - rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force) - { -@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .detect = rcar_du_lvds_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -- .destroy = rcar_du_lvds_connector_destroy, -+ .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - }; -@@ -117,9 +111,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu, - return ret; - - drm_connector_helper_add(connector, &connector_helper_funcs); -- ret = drm_connector_register(connector); -- if (ret < 0) -- return ret; - - connector->dpms = DRM_MODE_DPMS_OFF; - drm_object_property_set_value(&connector->base, -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c -index e0a5d8f93963..9d7e5c99caf6 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c -@@ -31,12 +31,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { - .best_encoder = rcar_du_connector_best_encoder, - }; - --static void rcar_du_vga_connector_destroy(struct drm_connector *connector) --{ -- drm_connector_unregister(connector); -- drm_connector_cleanup(connector); --} -- - static enum drm_connector_status - rcar_du_vga_connector_detect(struct drm_connector *connector, bool force) - { -@@ -48,7 +42,7 @@ static const struct drm_connector_funcs connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .detect = rcar_du_vga_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, -- .destroy = rcar_du_vga_connector_destroy, -+ .destroy = drm_connector_cleanup, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, - }; -@@ -76,9 +70,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, - return ret; - - drm_connector_helper_add(connector, &connector_helper_funcs); -- ret = drm_connector_register(connector); -- if (ret < 0) -- return ret; - - connector->dpms = DRM_MODE_DPMS_OFF; - drm_object_property_set_value(&connector->base, -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c -index ecf15cf0c3fd..04fd0f2b6af0 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c -@@ -471,7 +471,7 @@ static int vmw_cmd_invalid(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - SVGA3dCmdHeader *header) - { -- return capable(CAP_SYS_ADMIN) ? : -EINVAL; -+ return -EINVAL; - } - - static int vmw_cmd_ok(struct vmw_private *dev_priv, -diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 936960202cf4..11a051bd8a8b 100644 ---- a/drivers/hid/hid-core.c -+++ b/drivers/hid/hid-core.c -@@ -2427,6 +2427,7 @@ static const struct hid_device_id hid_ignore_list[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, - #if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE) -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index c7f8b70d15ee..37cbc2ecfc5f 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -777,6 +777,9 @@ - #define USB_VENDOR_ID_PETALYNX 0x18b1 - #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 - -+#define USB_VENDOR_ID_PETZL 0x2122 -+#define USB_DEVICE_ID_PETZL_HEADLAMP 0x1234 -+ - #define USB_VENDOR_ID_PHILIPS 0x0471 - #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 - -diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c -index 9eca4b41fa0a..b7a73f1a8beb 100644 ---- a/drivers/infiniband/core/uverbs_cmd.c -+++ b/drivers/infiniband/core/uverbs_cmd.c -@@ -2287,8 +2287,9 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, - if (copy_from_user(&cmd, buf, sizeof cmd)) - return -EFAULT; - -- if (cmd.port_num < rdma_start_port(ib_dev) || -- cmd.port_num > rdma_end_port(ib_dev)) -+ if ((cmd.attr_mask & IB_QP_PORT) && -+ (cmd.port_num < rdma_start_port(ib_dev) || -+ cmd.port_num > rdma_end_port(ib_dev))) - return -EINVAL; - - INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, -diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c -index deb89d63a728..e684be1bb7c0 100644 ---- a/drivers/irqchip/irq-keystone.c -+++ b/drivers/irqchip/irq-keystone.c -@@ -19,9 +19,9 @@ - #include - #include - #include -+#include - #include - #include --#include - #include - #include - #include -@@ -39,6 +39,7 @@ struct keystone_irq_device { - struct irq_domain *irqd; - struct regmap *devctrl_regs; - u32 devctrl_offset; -+ raw_spinlock_t wa_lock; - }; - - static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq) -@@ -83,17 +84,15 @@ static void keystone_irq_ack(struct irq_data *d) - /* nothing to do here */ - } - --static void keystone_irq_handler(struct irq_desc *desc) -+static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq) - { -- unsigned int irq = irq_desc_get_irq(desc); -- struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc); -+ struct keystone_irq_device *kirq = keystone_irq; -+ unsigned long wa_lock_flags; - unsigned long pending; - int src, virq; - - dev_dbg(kirq->dev, "start irq %d\n", irq); - -- chained_irq_enter(irq_desc_get_chip(desc), desc); -- - pending = keystone_irq_readl(kirq); - keystone_irq_writel(kirq, pending); - -@@ -111,13 +110,15 @@ static void keystone_irq_handler(struct irq_desc *desc) - if (!virq) - dev_warn(kirq->dev, "sporious irq detected hwirq %d, virq %d\n", - src, virq); -+ raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags); - generic_handle_irq(virq); -+ raw_spin_unlock_irqrestore(&kirq->wa_lock, -+ wa_lock_flags); - } - } - -- chained_irq_exit(irq_desc_get_chip(desc), desc); -- - dev_dbg(kirq->dev, "end irq %d\n", irq); -+ return IRQ_HANDLED; - } - - static int keystone_irq_map(struct irq_domain *h, unsigned int virq, -@@ -182,9 +183,16 @@ static int keystone_irq_probe(struct platform_device *pdev) - return -ENODEV; - } - -+ raw_spin_lock_init(&kirq->wa_lock); -+ - platform_set_drvdata(pdev, kirq); - -- irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq); -+ ret = request_irq(kirq->irq, keystone_irq_handler, -+ 0, dev_name(dev), kirq); -+ if (ret) { -+ irq_domain_remove(kirq->irqd); -+ return ret; -+ } - - /* clear all source bits */ - keystone_irq_writel(kirq, ~0x0); -@@ -199,6 +207,8 @@ static int keystone_irq_remove(struct platform_device *pdev) - struct keystone_irq_device *kirq = platform_get_drvdata(pdev); - int hwirq; - -+ free_irq(kirq->irq, kirq); -+ - for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++) - irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq)); - -diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c -index 17304705f2cf..05fa9f7af53c 100644 ---- a/drivers/irqchip/irq-mxs.c -+++ b/drivers/irqchip/irq-mxs.c -@@ -131,12 +131,16 @@ static struct irq_chip mxs_icoll_chip = { - .irq_ack = icoll_ack_irq, - .irq_mask = icoll_mask_irq, - .irq_unmask = icoll_unmask_irq, -+ .flags = IRQCHIP_MASK_ON_SUSPEND | -+ IRQCHIP_SKIP_SET_WAKE, - }; - - static struct irq_chip asm9260_icoll_chip = { - .irq_ack = icoll_ack_irq, - .irq_mask = asm9260_mask_irq, - .irq_unmask = asm9260_unmask_irq, -+ .flags = IRQCHIP_MASK_ON_SUSPEND | -+ IRQCHIP_SKIP_SET_WAKE, - }; - - asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) -diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c -index 9b856e1890d1..e4c43a17b333 100644 ---- a/drivers/isdn/i4l/isdn_common.c -+++ b/drivers/isdn/i4l/isdn_common.c -@@ -1379,6 +1379,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) - if (arg) { - if (copy_from_user(bname, argp, sizeof(bname) - 1)) - return -EFAULT; -+ bname[sizeof(bname)-1] = 0; - } else - return -EINVAL; - ret = mutex_lock_interruptible(&dev->mtx); -diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c -index aa5dd5668528..dbad5c431bcb 100644 ---- a/drivers/isdn/i4l/isdn_net.c -+++ b/drivers/isdn/i4l/isdn_net.c -@@ -2611,10 +2611,9 @@ isdn_net_newslave(char *parm) - char newname[10]; - - if (p) { -- /* Slave-Name MUST not be empty */ -- if (!strlen(p + 1)) -+ /* Slave-Name MUST not be empty or overflow 'newname' */ -+ if (strscpy(newname, p + 1, sizeof(newname)) <= 0) - return NULL; -- strcpy(newname, p + 1); - *p = 0; - /* Master must already exist */ - if (!(n = isdn_net_findif(parm))) -diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c -index 9c1e8adaf4fc..bf3fbd00a091 100644 ---- a/drivers/isdn/i4l/isdn_ppp.c -+++ b/drivers/isdn/i4l/isdn_ppp.c -@@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s - id); - return NULL; - } else { -- rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); -+ rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC); - if (!rs) - return NULL; - rs->state = CCPResetIdle; -diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c -index 6a4811f85705..9cf826df89b1 100644 ---- a/drivers/mailbox/mailbox.c -+++ b/drivers/mailbox/mailbox.c -@@ -104,11 +104,14 @@ static void tx_tick(struct mbox_chan *chan, int r) - /* Submit next message */ - msg_submit(chan); - -+ if (!mssg) -+ return; -+ - /* Notify the client */ -- if (mssg && chan->cl->tx_done) -+ if (chan->cl->tx_done) - chan->cl->tx_done(chan->cl, mssg, r); - -- if (chan->cl->tx_block) -+ if (r != -ETIME && chan->cl->tx_block) - complete(&chan->tx_complete); - } - -@@ -261,7 +264,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) - - msg_submit(chan); - -- if (chan->cl->tx_block && chan->active_req) { -+ if (chan->cl->tx_block) { - unsigned long wait; - int ret; - -@@ -272,8 +275,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) - - ret = wait_for_completion_timeout(&chan->tx_complete, wait); - if (ret == 0) { -- t = -EIO; -- tx_tick(chan, -EIO); -+ t = -ETIME; -+ tx_tick(chan, t); - } - } - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index fc182c4f2619..8f60520c8392 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -5821,6 +5821,8 @@ static void raid5_do_work(struct work_struct *work) - pr_debug("%d stripes handled\n", handled); - - spin_unlock_irq(&conf->device_lock); -+ -+ async_tx_issue_pending_all(); - blk_finish_plug(&plug); - - pr_debug("--- raid5worker inactive\n"); -diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c -index 8001cde1db1e..503135a4f47a 100644 ---- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c -+++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c -@@ -211,7 +211,7 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl) - } - - if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS) -- ret = s5c73m3_af_run(state, ~af_lock); -+ ret = s5c73m3_af_run(state, !af_lock); - - return ret; - } -diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c -index 2a9dd460a95f..e1f9e7cebf8f 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/icm.c -+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c -@@ -118,8 +118,13 @@ static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem, - if (!buf) - return -ENOMEM; - -+ if (offset_in_page(buf)) { -+ dma_free_coherent(dev, PAGE_SIZE << order, -+ buf, sg_dma_address(mem)); -+ return -ENOMEM; -+ } -+ - sg_set_buf(mem, buf, PAGE_SIZE << order); -- BUG_ON(mem->offset); - sg_dma_len(mem) = PAGE_SIZE << order; - return 0; - } -diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c -index 79ef799f88ab..c5ea1018cb47 100644 ---- a/drivers/net/ethernet/realtek/r8169.c -+++ b/drivers/net/ethernet/realtek/r8169.c -@@ -326,6 +326,7 @@ enum cfg_version { - static const struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, -diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c -index 480f3dae0780..4296066a7ad3 100644 ---- a/drivers/net/ethernet/renesas/sh_eth.c -+++ b/drivers/net/ethernet/renesas/sh_eth.c -@@ -750,6 +750,7 @@ static struct sh_eth_cpu_data sh7734_data = { - .tsu = 1, - .hw_crc = 1, - .select_mii = 1, -+ .shift_rd0 = 1, - }; - - /* SH7763 */ -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 0bfbabad4431..1d1e5f7723ab 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -1442,7 +1442,7 @@ static struct phy_driver genphy_driver[] = { - .phy_id = 0xffffffff, - .phy_id_mask = 0xffffffff, - .name = "Generic PHY", -- .soft_reset = genphy_soft_reset, -+ .soft_reset = genphy_no_soft_reset, - .config_init = genphy_config_init, - .features = PHY_GBIT_FEATURES | SUPPORTED_MII | - SUPPORTED_AUI | SUPPORTED_FIBRE | -diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c -index f64b25c221e8..cd93220c9b45 100644 ---- a/drivers/net/usb/kaweth.c -+++ b/drivers/net/usb/kaweth.c -@@ -1009,6 +1009,7 @@ static int kaweth_probe( - struct net_device *netdev; - const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - int result = 0; -+ int rv = -EIO; - - dev_dbg(dev, - "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n", -@@ -1029,6 +1030,7 @@ static int kaweth_probe( - kaweth = netdev_priv(netdev); - kaweth->dev = udev; - kaweth->net = netdev; -+ kaweth->intf = intf; - - spin_lock_init(&kaweth->device_lock); - init_waitqueue_head(&kaweth->term_wait); -@@ -1048,6 +1050,10 @@ static int kaweth_probe( - /* Download the firmware */ - dev_info(dev, "Downloading firmware...\n"); - kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); -+ if (!kaweth->firmware_buf) { -+ rv = -ENOMEM; -+ goto err_free_netdev; -+ } - if ((result = kaweth_download_firmware(kaweth, - "kaweth/new_code.bin", - 100, -@@ -1139,8 +1145,6 @@ err_fw: - - dev_dbg(dev, "Initializing net device.\n"); - -- kaweth->intf = intf; -- - kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kaweth->tx_urb) - goto err_free_netdev; -@@ -1204,7 +1208,7 @@ err_only_tx: - err_free_netdev: - free_netdev(netdev); - -- return -EIO; -+ return rv; - } - - /**************************************************************** -diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h -index 8f4f6a892581..cfed5808bc4e 100644 ---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h -+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h -@@ -639,6 +639,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, - struct sk_buff *skb; - u32 cmd_id; - -+ if (!ar->wmi.ops->gen_vdev_spectral_conf) -+ return -EOPNOTSUPP; -+ - skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg); - if (IS_ERR(skb)) - return PTR_ERR(skb); -@@ -654,6 +657,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, - struct sk_buff *skb; - u32 cmd_id; - -+ if (!ar->wmi.ops->gen_vdev_spectral_enable) -+ return -EOPNOTSUPP; -+ - skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger, - enable); - if (IS_ERR(skb)) -diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c -index bb69a5949aea..85bca557a339 100644 ---- a/drivers/net/wireless/ath/wil6210/main.c -+++ b/drivers/net/wireless/ath/wil6210/main.c -@@ -330,18 +330,19 @@ static void wil_fw_error_worker(struct work_struct *work) - - wil->last_fw_recovery = jiffies; - -+ wil_info(wil, "fw error recovery requested (try %d)...\n", -+ wil->recovery_count); -+ if (!no_fw_recovery) -+ wil->recovery_state = fw_recovery_running; -+ if (wil_wait_for_recovery(wil) != 0) -+ return; -+ - mutex_lock(&wil->mutex); - switch (wdev->iftype) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_MONITOR: -- wil_info(wil, "fw error recovery requested (try %d)...\n", -- wil->recovery_count); -- if (!no_fw_recovery) -- wil->recovery_state = fw_recovery_running; -- if (0 != wil_wait_for_recovery(wil)) -- break; -- -+ /* silent recovery, upper layers will see disconnect */ - __wil_down(wil); - __wil_up(wil); - break; -diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c -index 532db28145c7..a5d7332dfce5 100644 ---- a/drivers/nfc/fdp/i2c.c -+++ b/drivers/nfc/fdp/i2c.c -@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id) - struct sk_buff *skb; - int r; - -- client = phy->i2c_dev; -- dev_dbg(&client->dev, "%s\n", __func__); -- - if (!phy || irq != phy->i2c_dev->irq) { - WARN_ON_ONCE(1); - return IRQ_NONE; - } - -+ client = phy->i2c_dev; -+ dev_dbg(&client->dev, "%s\n", __func__); -+ - r = fdp_nci_i2c_read(phy, &skb); - - if (r == -EREMOTEIO) -diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c -index efb2c1ceef98..957234272ef7 100644 ---- a/drivers/nvdimm/btt.c -+++ b/drivers/nvdimm/btt.c -@@ -1205,10 +1205,13 @@ static int btt_rw_page(struct block_device *bdev, sector_t sector, - struct page *page, int rw) - { - struct btt *btt = bdev->bd_disk->private_data; -+ int rc; - -- btt_do_bvec(btt, NULL, page, PAGE_CACHE_SIZE, 0, rw, sector); -- page_endio(page, rw & WRITE, 0); -- return 0; -+ rc = btt_do_bvec(btt, NULL, page, PAGE_CACHE_SIZE, 0, rw, sector); -+ if (rc == 0) -+ page_endio(page, rw & WRITE, 0); -+ -+ return rc; - } - - -diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c -index b7971d410b60..74e5360c53f0 100644 ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -88,7 +88,7 @@ static struct nvmem_config imx_ocotp_nvmem_config = { - - static const struct of_device_id imx_ocotp_dt_ids[] = { - { .compatible = "fsl,imx6q-ocotp", (void *)128 }, -- { .compatible = "fsl,imx6sl-ocotp", (void *)32 }, -+ { .compatible = "fsl,imx6sl-ocotp", (void *)64 }, - { .compatible = "fsl,imx6sx-ocotp", (void *)128 }, - { }, - }; -diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h -index ce129e595b55..5c935847599c 100644 ---- a/drivers/scsi/fnic/fnic.h -+++ b/drivers/scsi/fnic/fnic.h -@@ -248,6 +248,7 @@ struct fnic { - struct completion *remove_wait; /* device remove thread blocks */ - - atomic_t in_flight; /* io counter */ -+ bool internal_reset_inprogress; - u32 _reserved; /* fill hole */ - unsigned long state_flags; /* protected by host lock */ - enum fnic_state state; -diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c -index 266b909fe854..82e4bc8c11c5 100644 ---- a/drivers/scsi/fnic/fnic_scsi.c -+++ b/drivers/scsi/fnic/fnic_scsi.c -@@ -2533,6 +2533,19 @@ int fnic_host_reset(struct scsi_cmnd *sc) - unsigned long wait_host_tmo; - struct Scsi_Host *shost = sc->device->host; - struct fc_lport *lp = shost_priv(shost); -+ struct fnic *fnic = lport_priv(lp); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&fnic->fnic_lock, flags); -+ if (fnic->internal_reset_inprogress == 0) { -+ fnic->internal_reset_inprogress = 1; -+ } else { -+ spin_unlock_irqrestore(&fnic->fnic_lock, flags); -+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, -+ "host reset in progress skipping another host reset\n"); -+ return SUCCESS; -+ } -+ spin_unlock_irqrestore(&fnic->fnic_lock, flags); - - /* - * If fnic_reset is successful, wait for fabric login to complete -@@ -2553,6 +2566,9 @@ int fnic_host_reset(struct scsi_cmnd *sc) - } - } - -+ spin_lock_irqsave(&fnic->fnic_lock, flags); -+ fnic->internal_reset_inprogress = 0; -+ spin_unlock_irqrestore(&fnic->fnic_lock, flags); - return ret; - } - -diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c -index 5b2c37f1e908..9b5367294116 100644 ---- a/drivers/scsi/mpt3sas/mpt3sas_base.c -+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c -@@ -4981,15 +4981,14 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - static int - _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) - { -- int r, i; -+ int r, i, index; - unsigned long flags; - u32 reply_address; - u16 smid; - struct _tr_list *delayed_tr, *delayed_tr_next; - u8 hide_flag; - struct adapter_reply_queue *reply_q; -- long reply_post_free; -- u32 reply_post_free_sz, index = 0; -+ Mpi2ReplyDescriptorsUnion_t *reply_post_free_contig; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); -@@ -5061,27 +5060,27 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) - _base_assign_reply_queues(ioc); - - /* initialize Reply Post Free Queue */ -- reply_post_free_sz = ioc->reply_post_queue_depth * -- sizeof(Mpi2DefaultReplyDescriptor_t); -- reply_post_free = (long)ioc->reply_post[index].reply_post_free; -+ index = 0; -+ reply_post_free_contig = ioc->reply_post[0].reply_post_free; - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { -+ /* -+ * If RDPQ is enabled, switch to the next allocation. -+ * Otherwise advance within the contiguous region. -+ */ -+ if (ioc->rdpq_array_enable) { -+ reply_q->reply_post_free = -+ ioc->reply_post[index++].reply_post_free; -+ } else { -+ reply_q->reply_post_free = reply_post_free_contig; -+ reply_post_free_contig += ioc->reply_post_queue_depth; -+ } -+ - reply_q->reply_post_host_index = 0; -- reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) -- reply_post_free; - for (i = 0; i < ioc->reply_post_queue_depth; i++) - reply_q->reply_post_free[i].Words = - cpu_to_le64(ULLONG_MAX); - if (!_base_is_controller_msix_enabled(ioc)) - goto skip_init_reply_post_free_queue; -- /* -- * If RDPQ is enabled, switch to the next allocation. -- * Otherwise advance within the contiguous region. -- */ -- if (ioc->rdpq_array_enable) -- reply_post_free = (long) -- ioc->reply_post[++index].reply_post_free; -- else -- reply_post_free += reply_post_free_sz; - } - skip_init_reply_post_free_queue: - -diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c -index 2b3c25371d76..8175f997e82c 100644 ---- a/drivers/scsi/snic/snic_main.c -+++ b/drivers/scsi/snic/snic_main.c -@@ -584,6 +584,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) - if (!pool) { - SNIC_HOST_ERR(shost, "dflt sgl pool creation failed\n"); - -+ ret = -ENOMEM; - goto err_free_res; - } - -@@ -594,6 +595,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) - if (!pool) { - SNIC_HOST_ERR(shost, "max sgl pool creation failed\n"); - -+ ret = -ENOMEM; - goto err_free_dflt_sgl_pool; - } - -@@ -604,6 +606,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) - if (!pool) { - SNIC_HOST_ERR(shost, "snic tmreq info pool creation failed.\n"); - -+ ret = -ENOMEM; - goto err_free_max_sgl_pool; - } - -diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c -index 882cd6618cd5..87a0e47eeae6 100644 ---- a/drivers/spi/spi-dw.c -+++ b/drivers/spi/spi-dw.c -@@ -107,7 +107,10 @@ static const struct file_operations dw_spi_regs_ops = { - - static int dw_spi_debugfs_init(struct dw_spi *dws) - { -- dws->debugfs = debugfs_create_dir("dw_spi", NULL); -+ char name[128]; -+ -+ snprintf(name, 128, "dw_spi-%s", dev_name(&dws->master->dev)); -+ dws->debugfs = debugfs_create_dir(name, NULL); - if (!dws->debugfs) - return -ENOMEM; - -diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c -index 8fed55342b0f..b831f08e2769 100644 ---- a/drivers/staging/comedi/comedi_fops.c -+++ b/drivers/staging/comedi/comedi_fops.c -@@ -2901,9 +2901,6 @@ static int __init comedi_init(void) - - comedi_class->dev_groups = comedi_dev_groups; - -- /* XXX requires /proc interface */ -- comedi_proc_init(); -- - /* create devices files for legacy/manual use */ - for (i = 0; i < comedi_num_legacy_minors; i++) { - struct comedi_device *dev; -@@ -2921,6 +2918,9 @@ static int __init comedi_init(void) - mutex_unlock(&dev->mutex); - } - -+ /* XXX requires /proc interface */ -+ comedi_proc_init(); -+ - return 0; - } - module_init(comedi_init); -diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c -index 99285b416308..ee579ba2b59e 100644 ---- a/drivers/usb/gadget/function/f_hid.c -+++ b/drivers/usb/gadget/function/f_hid.c -@@ -539,7 +539,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) - } - status = usb_ep_enable(hidg->out_ep); - if (status < 0) { -- ERROR(cdev, "Enable IN endpoint FAILED!\n"); -+ ERROR(cdev, "Enable OUT endpoint FAILED!\n"); - goto fail; - } - hidg->out_ep->driver_data = hidg; -diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c -index 830e2fd47642..b31b84f56e8f 100644 ---- a/drivers/vfio/pci/vfio_pci.c -+++ b/drivers/vfio/pci/vfio_pci.c -@@ -902,6 +902,10 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) - return ret; - - vdev->barmap[index] = pci_iomap(pdev, index, 0); -+ if (!vdev->barmap[index]) { -+ pci_release_selected_regions(pdev, 1 << index); -+ return -ENOMEM; -+ } - } - - vma->vm_private_data = vdev; -diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c -index 210db24d2204..4d39f7959adf 100644 ---- a/drivers/vfio/pci/vfio_pci_rdwr.c -+++ b/drivers/vfio/pci/vfio_pci_rdwr.c -@@ -190,7 +190,10 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf, - if (!vdev->has_vga) - return -EINVAL; - -- switch (pos) { -+ if (pos > 0xbfffful) -+ return -EINVAL; -+ -+ switch ((u32)pos) { - case 0xa0000 ... 0xbffff: - count = min(count, (size_t)(0xc0000 - pos)); - iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1); -diff --git a/drivers/video/fbdev/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c -index 07675d6f323e..d4530b54479c 100644 ---- a/drivers/video/fbdev/cobalt_lcdfb.c -+++ b/drivers/video/fbdev/cobalt_lcdfb.c -@@ -350,6 +350,11 @@ static int cobalt_lcdfb_probe(struct platform_device *dev) - info->screen_size = resource_size(res); - info->screen_base = devm_ioremap(&dev->dev, res->start, - info->screen_size); -+ if (!info->screen_base) { -+ framebuffer_release(info); -+ return -ENOMEM; -+ } -+ - info->fbops = &cobalt_lcd_fbops; - info->fix = cobalt_lcdfb_fix; - info->fix.smem_start = res->start; -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index a61926cb01c0..bebd6517355d 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -7521,11 +7521,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode, - * within our reservation, otherwise we need to adjust our inode - * counter appropriately. - */ -- if (dio_data->outstanding_extents) { -+ if (dio_data->outstanding_extents >= num_extents) { - dio_data->outstanding_extents -= num_extents; - } else { -+ /* -+ * If dio write length has been split due to no large enough -+ * contiguous space, we need to compensate our inode counter -+ * appropriately. -+ */ -+ u64 num_needed = num_extents - dio_data->outstanding_extents; -+ - spin_lock(&BTRFS_I(inode)->lock); -- BTRFS_I(inode)->outstanding_extents += num_extents; -+ BTRFS_I(inode)->outstanding_extents += num_needed; - spin_unlock(&BTRFS_I(inode)->lock); - } - } -diff --git a/fs/dcache.c b/fs/dcache.c -index 3000cbb54949..3ed642e0a0c2 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -269,6 +269,33 @@ static inline int dname_external(const struct dentry *dentry) - return dentry->d_name.name != dentry->d_iname; - } - -+void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry) -+{ -+ spin_lock(&dentry->d_lock); -+ if (unlikely(dname_external(dentry))) { -+ struct external_name *p = external_name(dentry); -+ atomic_inc(&p->u.count); -+ spin_unlock(&dentry->d_lock); -+ name->name = p->name; -+ } else { -+ memcpy(name->inline_name, dentry->d_iname, DNAME_INLINE_LEN); -+ spin_unlock(&dentry->d_lock); -+ name->name = name->inline_name; -+ } -+} -+EXPORT_SYMBOL(take_dentry_name_snapshot); -+ -+void release_dentry_name_snapshot(struct name_snapshot *name) -+{ -+ if (unlikely(name->name != name->inline_name)) { -+ struct external_name *p; -+ p = container_of(name->name, struct external_name, name[0]); -+ if (unlikely(atomic_dec_and_test(&p->u.count))) -+ kfree_rcu(p, u.head); -+ } -+} -+EXPORT_SYMBOL(release_dentry_name_snapshot); -+ - static inline void __d_set_inode_and_type(struct dentry *dentry, - struct inode *inode, - unsigned type_flags) -diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c -index 0f5d05bf2131..e49ba072bd64 100644 ---- a/fs/debugfs/inode.c -+++ b/fs/debugfs/inode.c -@@ -669,7 +669,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, - { - int error; - struct dentry *dentry = NULL, *trap; -- const char *old_name; -+ struct name_snapshot old_name; - - trap = lock_rename(new_dir, old_dir); - /* Source or destination directories don't exist? */ -@@ -684,19 +684,19 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, - if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry)) - goto exit; - -- old_name = fsnotify_oldname_init(old_dentry->d_name.name); -+ take_dentry_name_snapshot(&old_name, old_dentry); - - error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir), - dentry); - if (error) { -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - goto exit; - } - d_move(old_dentry, dentry); -- fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name, -+ fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name.name, - d_is_dir(old_dentry), - NULL, old_dentry); -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - unlock_rename(new_dir, old_dir); - dput(dentry); - return old_dentry; -diff --git a/fs/namei.c b/fs/namei.c -index 0b0acba72a71..3f96ae087488 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -4179,11 +4179,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - { - int error; - bool is_dir = d_is_dir(old_dentry); -- const unsigned char *old_name; - struct inode *source = old_dentry->d_inode; - struct inode *target = new_dentry->d_inode; - bool new_is_dir = false; - unsigned max_links = new_dir->i_sb->s_max_links; -+ struct name_snapshot old_name; - - /* - * Check source == target. -@@ -4237,7 +4237,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - if (error) - return error; - -- old_name = fsnotify_oldname_init(old_dentry->d_name.name); -+ take_dentry_name_snapshot(&old_name, old_dentry); - dget(new_dentry); - if (!is_dir || (flags & RENAME_EXCHANGE)) - lock_two_nondirectories(source, target); -@@ -4298,14 +4298,14 @@ out: - mutex_unlock(&target->i_mutex); - dput(new_dentry); - if (!error) { -- fsnotify_move(old_dir, new_dir, old_name, is_dir, -+ fsnotify_move(old_dir, new_dir, old_name.name, is_dir, - !(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry); - if (flags & RENAME_EXCHANGE) { - fsnotify_move(new_dir, old_dir, old_dentry->d_name.name, - new_is_dir, NULL, new_dentry); - } - } -- fsnotify_oldname_free(old_name); -+ release_dentry_name_snapshot(&old_name); - - return error; - } -diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c -index db39de2dd4cb..a64adc2fced9 100644 ---- a/fs/notify/fsnotify.c -+++ b/fs/notify/fsnotify.c -@@ -104,16 +104,20 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) - if (unlikely(!fsnotify_inode_watches_children(p_inode))) - __fsnotify_update_child_dentry_flags(p_inode); - else if (p_inode->i_fsnotify_mask & mask) { -+ struct name_snapshot name; -+ - /* we are notifying a parent so come up with the new mask which - * specifies these are events which came from a child. */ - mask |= FS_EVENT_ON_CHILD; - -+ take_dentry_name_snapshot(&name, dentry); - if (path) - ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, -- dentry->d_name.name, 0); -+ name.name, 0); - else - ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, -- dentry->d_name.name, 0); -+ name.name, 0); -+ release_dentry_name_snapshot(&name); - } - - dput(parent); -diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c -index 905caba36529..59d93acc29c7 100644 ---- a/fs/pstore/ram.c -+++ b/fs/pstore/ram.c -@@ -413,7 +413,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, - for (i = 0; i < cxt->max_dump_cnt; i++) { - cxt->przs[i] = persistent_ram_new(*paddr, cxt->record_size, 0, - &cxt->ecc_info, -- cxt->memtype); -+ cxt->memtype, 0); - if (IS_ERR(cxt->przs[i])) { - err = PTR_ERR(cxt->przs[i]); - dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", -@@ -450,7 +450,8 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, - return -ENOMEM; - } - -- *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype); -+ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, -+ cxt->memtype, 0); - if (IS_ERR(*prz)) { - int err = PTR_ERR(*prz); - -diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c -index 364d2dffe5a6..27300533c2dd 100644 ---- a/fs/pstore/ram_core.c -+++ b/fs/pstore/ram_core.c -@@ -47,16 +47,15 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz) - return atomic_read(&prz->buffer->start); - } - --static DEFINE_RAW_SPINLOCK(buffer_lock); -- - /* increase and wrap the start pointer, returning the old value */ - static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) - { - int old; - int new; -- unsigned long flags; -+ unsigned long flags = 0; - -- raw_spin_lock_irqsave(&buffer_lock, flags); -+ if (!(prz->flags & PRZ_FLAG_NO_LOCK)) -+ raw_spin_lock_irqsave(&prz->buffer_lock, flags); - - old = atomic_read(&prz->buffer->start); - new = old + a; -@@ -64,7 +63,8 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a) - new -= prz->buffer_size; - atomic_set(&prz->buffer->start, new); - -- raw_spin_unlock_irqrestore(&buffer_lock, flags); -+ if (!(prz->flags & PRZ_FLAG_NO_LOCK)) -+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); - - return old; - } -@@ -74,9 +74,10 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a) - { - size_t old; - size_t new; -- unsigned long flags; -+ unsigned long flags = 0; - -- raw_spin_lock_irqsave(&buffer_lock, flags); -+ if (!(prz->flags & PRZ_FLAG_NO_LOCK)) -+ raw_spin_lock_irqsave(&prz->buffer_lock, flags); - - old = atomic_read(&prz->buffer->size); - if (old == prz->buffer_size) -@@ -88,7 +89,8 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a) - atomic_set(&prz->buffer->size, new); - - exit: -- raw_spin_unlock_irqrestore(&buffer_lock, flags); -+ if (!(prz->flags & PRZ_FLAG_NO_LOCK)) -+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags); - } - - static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, -@@ -448,6 +450,7 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig, - prz->buffer->sig); - } - -+ /* Rewind missing or invalid memory area. */ - prz->buffer->sig = sig; - persistent_ram_zap(prz); - -@@ -474,7 +477,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz) - - struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, - u32 sig, struct persistent_ram_ecc_info *ecc_info, -- unsigned int memtype) -+ unsigned int memtype, u32 flags) - { - struct persistent_ram_zone *prz; - int ret = -ENOMEM; -@@ -485,6 +488,10 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, - goto err; - } - -+ /* Initialize general buffer state. */ -+ raw_spin_lock_init(&prz->buffer_lock); -+ prz->flags = flags; -+ - ret = persistent_ram_buffer_map(start, size, prz, memtype); - if (ret) - goto err; -diff --git a/fs/seq_file.c b/fs/seq_file.c -index d672e2fec459..6dc4296eed62 100644 ---- a/fs/seq_file.c -+++ b/fs/seq_file.c -@@ -72,9 +72,10 @@ int seq_open(struct file *file, const struct seq_operations *op) - - mutex_init(&p->lock); - p->op = op; --#ifdef CONFIG_USER_NS -- p->user_ns = file->f_cred->user_ns; --#endif -+ -+ // No refcounting: the lifetime of 'p' is constrained -+ // to the lifetime of the file. -+ p->file = file; - - /* - * Wrappers around seq_open(e.g. swaps_open) need to be -diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c -index 187b80267ff9..a9063ac50c4e 100644 ---- a/fs/xfs/xfs_aops.c -+++ b/fs/xfs/xfs_aops.c -@@ -1426,6 +1426,26 @@ __xfs_get_blocks( - if (error) - goto out_unlock; - -+ /* -+ * The only time we can ever safely find delalloc blocks on direct I/O -+ * is a dio write to post-eof speculative preallocation. All other -+ * scenarios are indicative of a problem or misuse (such as mixing -+ * direct and mapped I/O). -+ * -+ * The file may be unmapped by the time we get here so we cannot -+ * reliably fail the I/O based on mapping. Instead, fail the I/O if this -+ * is a read or a write within eof. Otherwise, carry on but warn as a -+ * precuation if the file happens to be mapped. -+ */ -+ if (direct && imap.br_startblock == DELAYSTARTBLOCK) { -+ if (!create || offset < i_size_read(VFS_I(ip))) { -+ WARN_ON_ONCE(1); -+ error = -EIO; -+ goto out_unlock; -+ } -+ WARN_ON_ONCE(mapping_mapped(VFS_I(ip)->i_mapping)); -+ } -+ - /* for DAX, we convert unwritten extents directly */ - if (create && - (!nimaps || -@@ -1525,7 +1545,6 @@ __xfs_get_blocks( - set_buffer_new(bh_result); - - if (imap.br_startblock == DELAYSTARTBLOCK) { -- BUG_ON(direct); - if (create) { - set_buffer_uptodate(bh_result); - set_buffer_mapped(bh_result); -diff --git a/include/linux/dcache.h b/include/linux/dcache.h -index 8d7151eb6ceb..d516847e0fae 100644 ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -615,5 +615,11 @@ static inline struct inode *d_real_inode(struct dentry *dentry) - return d_backing_inode(d_real(dentry)); - } - -+struct name_snapshot { -+ const char *name; -+ char inline_name[DNAME_INLINE_LEN]; -+}; -+void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *); -+void release_dentry_name_snapshot(struct name_snapshot *); - - #endif /* __LINUX_DCACHE_H */ -diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h -index 7ee1774edee5..a7789559078b 100644 ---- a/include/linux/fsnotify.h -+++ b/include/linux/fsnotify.h -@@ -310,35 +310,4 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) - } - } - --#if defined(CONFIG_FSNOTIFY) /* notify helpers */ -- --/* -- * fsnotify_oldname_init - save off the old filename before we change it -- */ --static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name) --{ -- return kstrdup(name, GFP_KERNEL); --} -- --/* -- * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init -- */ --static inline void fsnotify_oldname_free(const unsigned char *old_name) --{ -- kfree(old_name); --} -- --#else /* CONFIG_FSNOTIFY */ -- --static inline const char *fsnotify_oldname_init(const unsigned char *name) --{ -- return NULL; --} -- --static inline void fsnotify_oldname_free(const unsigned char *old_name) --{ --} -- --#endif /* CONFIG_FSNOTIFY */ -- - #endif /* _LINUX_FS_NOTIFY_H */ -diff --git a/include/linux/phy.h b/include/linux/phy.h -index 05fde31b6dc6..b64825d6ad26 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -785,6 +785,10 @@ int genphy_read_status(struct phy_device *phydev); - int genphy_suspend(struct phy_device *phydev); - int genphy_resume(struct phy_device *phydev); - int genphy_soft_reset(struct phy_device *phydev); -+static inline int genphy_no_soft_reset(struct phy_device *phydev) -+{ -+ return 0; -+} - void phy_driver_unregister(struct phy_driver *drv); - void phy_drivers_unregister(struct phy_driver *drv, int n); - int phy_driver_register(struct phy_driver *new_driver); -diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h -index 9c9d6c154c8e..6f4520a82197 100644 ---- a/include/linux/pstore_ram.h -+++ b/include/linux/pstore_ram.h -@@ -23,6 +23,13 @@ - #include - #include - -+/* -+ * Choose whether access to the RAM zone requires locking or not. If a zone -+ * can be written to from different CPUs like with ftrace for example, then -+ * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required. -+ */ -+#define PRZ_FLAG_NO_LOCK BIT(0) -+ - struct persistent_ram_buffer; - struct rs_control; - -@@ -39,6 +46,8 @@ struct persistent_ram_zone { - void *vaddr; - struct persistent_ram_buffer *buffer; - size_t buffer_size; -+ u32 flags; -+ raw_spinlock_t buffer_lock; - - /* ECC correction */ - char *par_buffer; -@@ -54,7 +63,7 @@ struct persistent_ram_zone { - - struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, - u32 sig, struct persistent_ram_ecc_info *ecc_info, -- unsigned int memtype); -+ unsigned int memtype, u32 flags); - void persistent_ram_free(struct persistent_ram_zone *prz); - void persistent_ram_zap(struct persistent_ram_zone *prz); - -diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h -index dde00defbaa5..f3d45dd42695 100644 ---- a/include/linux/seq_file.h -+++ b/include/linux/seq_file.h -@@ -7,13 +7,10 @@ - #include - #include - #include -+#include -+#include - - struct seq_operations; --struct file; --struct path; --struct inode; --struct dentry; --struct user_namespace; - - struct seq_file { - char *buf; -@@ -27,9 +24,7 @@ struct seq_file { - struct mutex lock; - const struct seq_operations *op; - int poll_event; --#ifdef CONFIG_USER_NS -- struct user_namespace *user_ns; --#endif -+ const struct file *file; - void *private; - }; - -@@ -147,7 +142,7 @@ int seq_release_private(struct inode *, struct file *); - static inline struct user_namespace *seq_user_ns(struct seq_file *seq) - { - #ifdef CONFIG_USER_NS -- return seq->user_ns; -+ return seq->file->f_cred->user_ns; - #else - extern struct user_namespace init_user_ns; - return &init_user_ns; -diff --git a/kernel/resource.c b/kernel/resource.c -index 249b1eb1e6e1..a4a94e700fb9 100644 ---- a/kernel/resource.c -+++ b/kernel/resource.c -@@ -105,16 +105,25 @@ static int r_show(struct seq_file *m, void *v) - { - struct resource *root = m->private; - struct resource *r = v, *p; -+ unsigned long long start, end; - int width = root->end < 0x10000 ? 4 : 8; - int depth; - - for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) - if (p->parent == root) - break; -+ -+ if (file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) { -+ start = r->start; -+ end = r->end; -+ } else { -+ start = end = 0; -+ } -+ - seq_printf(m, "%*s%0*llx-%0*llx : %s\n", - depth * 2, "", -- width, (unsigned long long) r->start, -- width, (unsigned long long) r->end, -+ width, start, -+ width, end, - r->name ? r->name : ""); - return 0; - } -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index c436426a80dd..dece705b7f8c 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -5553,7 +5553,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) - - case CPU_UP_PREPARE: - rq->calc_load_update = calc_load_update; -- account_reset_rq(rq); - break; - - case CPU_ONLINE: -@@ -8253,11 +8252,20 @@ cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) - if (IS_ERR(tg)) - return ERR_PTR(-ENOMEM); - -- sched_online_group(tg, parent); -- - return &tg->css; - } - -+/* Expose task group only after completing cgroup initialization */ -+static int cpu_cgroup_css_online(struct cgroup_subsys_state *css) -+{ -+ struct task_group *tg = css_tg(css); -+ struct task_group *parent = css_tg(css->parent); -+ -+ if (parent) -+ sched_online_group(tg, parent); -+ return 0; -+} -+ - static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) - { - struct task_group *tg = css_tg(css); -@@ -8632,6 +8640,7 @@ static struct cftype cpu_files[] = { - - struct cgroup_subsys cpu_cgrp_subsys = { - .css_alloc = cpu_cgroup_css_alloc, -+ .css_online = cpu_cgroup_css_online, - .css_released = cpu_cgroup_css_released, - .css_free = cpu_cgroup_css_free, - .fork = cpu_cgroup_fork, -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 4e5db65d1aab..55d92a1ca070 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -1770,16 +1770,3 @@ static inline u64 irq_time_read(int cpu) - } - #endif /* CONFIG_64BIT */ - #endif /* CONFIG_IRQ_TIME_ACCOUNTING */ -- --static inline void account_reset_rq(struct rq *rq) --{ --#ifdef CONFIG_IRQ_TIME_ACCOUNTING -- rq->prev_irq_time = 0; --#endif --#ifdef CONFIG_PARAVIRT -- rq->prev_steal_time = 0; --#endif --#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING -- rq->prev_steal_time_rq = 0; --#endif --} -diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c -index e20ae2d3c498..5e4199d5a388 100644 ---- a/net/8021q/vlan.c -+++ b/net/8021q/vlan.c -@@ -292,6 +292,10 @@ static void vlan_sync_address(struct net_device *dev, - if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr)) - return; - -+ /* vlan continues to inherit address of lower device */ -+ if (vlan_dev_inherit_address(vlandev, dev)) -+ goto out; -+ - /* vlan address was different from the old address and is equal to - * the new address */ - if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) && -@@ -304,6 +308,7 @@ static void vlan_sync_address(struct net_device *dev, - !ether_addr_equal(vlandev->dev_addr, dev->dev_addr)) - dev_uc_add(dev, vlandev->dev_addr); - -+out: - ether_addr_copy(vlan->real_dev_addr, dev->dev_addr); - } - -diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h -index 9d010a09ab98..cc1557978066 100644 ---- a/net/8021q/vlan.h -+++ b/net/8021q/vlan.h -@@ -109,6 +109,8 @@ int vlan_check_real_dev(struct net_device *real_dev, - void vlan_setup(struct net_device *dev); - int register_vlan_dev(struct net_device *dev); - void unregister_vlan_dev(struct net_device *dev, struct list_head *head); -+bool vlan_dev_inherit_address(struct net_device *dev, -+ struct net_device *real_dev); - - static inline u32 vlan_get_ingress_priority(struct net_device *dev, - u16 vlan_tci) -diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c -index fded86508117..ca4dc9031073 100644 ---- a/net/8021q/vlan_dev.c -+++ b/net/8021q/vlan_dev.c -@@ -244,6 +244,17 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) - strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23); - } - -+bool vlan_dev_inherit_address(struct net_device *dev, -+ struct net_device *real_dev) -+{ -+ if (dev->addr_assign_type != NET_ADDR_STOLEN) -+ return false; -+ -+ ether_addr_copy(dev->dev_addr, real_dev->dev_addr); -+ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); -+ return true; -+} -+ - static int vlan_dev_open(struct net_device *dev) - { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); -@@ -254,7 +265,8 @@ static int vlan_dev_open(struct net_device *dev) - !(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) - return -ENETDOWN; - -- if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) { -+ if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) && -+ !vlan_dev_inherit_address(dev, real_dev)) { - err = dev_uc_add(real_dev, dev->dev_addr); - if (err < 0) - goto out; -@@ -558,8 +570,10 @@ static int vlan_dev_init(struct net_device *dev) - /* ipv6 shared card related stuff */ - dev->dev_id = real_dev->dev_id; - -- if (is_zero_ether_addr(dev->dev_addr)) -- eth_hw_addr_inherit(dev, real_dev); -+ if (is_zero_ether_addr(dev->dev_addr)) { -+ ether_addr_copy(dev->dev_addr, real_dev->dev_addr); -+ dev->addr_assign_type = NET_ADDR_STOLEN; -+ } - if (is_zero_ether_addr(dev->broadcast)) - memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len); - -diff --git a/net/core/dev.c b/net/core/dev.c -index dc5d3d546150..4b0853194a03 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2550,9 +2550,10 @@ EXPORT_SYMBOL(skb_mac_gso_segment); - static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) - { - if (tx_path) -- return skb->ip_summed != CHECKSUM_PARTIAL; -- else -- return skb->ip_summed == CHECKSUM_NONE; -+ return skb->ip_summed != CHECKSUM_PARTIAL && -+ skb->ip_summed != CHECKSUM_NONE; -+ -+ return skb->ip_summed == CHECKSUM_NONE; - } - - /** -@@ -2571,11 +2572,12 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) - struct sk_buff *__skb_gso_segment(struct sk_buff *skb, - netdev_features_t features, bool tx_path) - { -+ struct sk_buff *segs; -+ - if (unlikely(skb_needs_check(skb, tx_path))) { - int err; - -- skb_warn_bad_offload(skb); -- -+ /* We're going to init ->check field in TCP or UDP header */ - err = skb_cow_head(skb, 0); - if (err < 0) - return ERR_PTR(err); -@@ -2590,7 +2592,12 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, - skb_reset_mac_header(skb); - skb_reset_mac_len(skb); - -- return skb_mac_gso_segment(skb, features); -+ segs = skb_mac_gso_segment(skb, features); -+ -+ if (unlikely(skb_needs_check(skb, tx_path))) -+ skb_warn_bad_offload(skb); -+ -+ return segs; - } - EXPORT_SYMBOL(__skb_gso_segment); - -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 7d339fc1057f..150b4923fb72 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1361,7 +1361,7 @@ emsgsize: - */ - - cork->length += length; -- if (((length > mtu) || -+ if ((((length + fragheaderlen) > mtu) || - (skb && skb_is_gso(skb))) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && -diff --git a/net/key/af_key.c b/net/key/af_key.c -index d8d95b6415e4..2e1050ec2cf0 100644 ---- a/net/key/af_key.c -+++ b/net/key/af_key.c -@@ -63,6 +63,7 @@ struct pfkey_sock { - } u; - struct sk_buff *skb; - } dump; -+ struct mutex dump_lock; - }; - - static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, -@@ -143,6 +144,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol, - { - struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - struct sock *sk; -+ struct pfkey_sock *pfk; - int err; - - if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) -@@ -157,6 +159,9 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol, - if (sk == NULL) - goto out; - -+ pfk = pfkey_sk(sk); -+ mutex_init(&pfk->dump_lock); -+ - sock->ops = &pfkey_ops; - sock_init_data(sock, sk); - -@@ -285,13 +290,23 @@ static int pfkey_do_dump(struct pfkey_sock *pfk) - struct sadb_msg *hdr; - int rc; - -+ mutex_lock(&pfk->dump_lock); -+ if (!pfk->dump.dump) { -+ rc = 0; -+ goto out; -+ } -+ - rc = pfk->dump.dump(pfk); -- if (rc == -ENOBUFS) -- return 0; -+ if (rc == -ENOBUFS) { -+ rc = 0; -+ goto out; -+ } - - if (pfk->dump.skb) { -- if (!pfkey_can_dump(&pfk->sk)) -- return 0; -+ if (!pfkey_can_dump(&pfk->sk)) { -+ rc = 0; -+ goto out; -+ } - - hdr = (struct sadb_msg *) pfk->dump.skb->data; - hdr->sadb_msg_seq = 0; -@@ -302,6 +317,9 @@ static int pfkey_do_dump(struct pfkey_sock *pfk) - } - - pfkey_terminate_dump(pfk); -+ -+out: -+ mutex_unlock(&pfk->dump_lock); - return rc; - } - -@@ -1806,19 +1824,26 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms - struct xfrm_address_filter *filter = NULL; - struct pfkey_sock *pfk = pfkey_sk(sk); - -- if (pfk->dump.dump != NULL) -+ mutex_lock(&pfk->dump_lock); -+ if (pfk->dump.dump != NULL) { -+ mutex_unlock(&pfk->dump_lock); - return -EBUSY; -+ } - - proto = pfkey_satype2proto(hdr->sadb_msg_satype); -- if (proto == 0) -+ if (proto == 0) { -+ mutex_unlock(&pfk->dump_lock); - return -EINVAL; -+ } - - if (ext_hdrs[SADB_X_EXT_FILTER - 1]) { - struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1]; - - filter = kmalloc(sizeof(*filter), GFP_KERNEL); -- if (filter == NULL) -+ if (filter == NULL) { -+ mutex_unlock(&pfk->dump_lock); - return -ENOMEM; -+ } - - memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr, - sizeof(xfrm_address_t)); -@@ -1834,6 +1859,7 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms - pfk->dump.dump = pfkey_dump_sa; - pfk->dump.done = pfkey_dump_sa_done; - xfrm_state_walk_init(&pfk->dump.u.state, proto, filter); -+ mutex_unlock(&pfk->dump_lock); - - return pfkey_do_dump(pfk); - } -@@ -2693,14 +2719,18 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb - { - struct pfkey_sock *pfk = pfkey_sk(sk); - -- if (pfk->dump.dump != NULL) -+ mutex_lock(&pfk->dump_lock); -+ if (pfk->dump.dump != NULL) { -+ mutex_unlock(&pfk->dump_lock); - return -EBUSY; -+ } - - pfk->dump.msg_version = hdr->sadb_msg_version; - pfk->dump.msg_portid = hdr->sadb_msg_pid; - pfk->dump.dump = pfkey_dump_sp; - pfk->dump.done = pfkey_dump_sp_done; - xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN); -+ mutex_unlock(&pfk->dump_lock); - - return pfkey_do_dump(pfk); - } -diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c -index 8a0fdd870395..77055a362041 100644 ---- a/net/xfrm/xfrm_policy.c -+++ b/net/xfrm/xfrm_policy.c -@@ -1216,7 +1216,7 @@ static inline int policy_to_flow_dir(int dir) - } - - static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, -- const struct flowi *fl) -+ const struct flowi *fl, u16 family) - { - struct xfrm_policy *pol; - struct net *net = sock_net(sk); -@@ -1225,8 +1225,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, - read_lock_bh(&net->xfrm.xfrm_policy_lock); - pol = rcu_dereference(sk->sk_policy[dir]); - if (pol != NULL) { -- bool match = xfrm_selector_match(&pol->selector, fl, -- sk->sk_family); -+ bool match = xfrm_selector_match(&pol->selector, fl, family); - int err = 0; - - if (match) { -@@ -2174,7 +2173,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, - sk = sk_const_to_full_sk(sk); - if (sk && sk->sk_policy[XFRM_POLICY_OUT]) { - num_pols = 1; -- pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); -+ pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family); - err = xfrm_expand_policies(fl, family, pols, - &num_pols, &num_xfrms); - if (err < 0) -@@ -2453,7 +2452,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, - pol = NULL; - sk = sk_to_full_sk(sk); - if (sk && sk->sk_policy[dir]) { -- pol = xfrm_sk_policy_lookup(sk, dir, &fl); -+ pol = xfrm_sk_policy_lookup(sk, dir, &fl, family); - if (IS_ERR(pol)) { - XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); - return 0; -diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c -index c1b87c5800b1..b3fddba4c084 100644 ---- a/sound/soc/codecs/nau8825.c -+++ b/sound/soc/codecs/nau8825.c -@@ -936,7 +936,8 @@ static void nau8825_fll_apply(struct nau8825 *nau8825, - NAU8825_FLL_INTEGER_MASK, fll_param->fll_int); - /* FLL pre-scaler */ - regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL4, -- NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div); -+ NAU8825_FLL_REF_DIV_MASK, -+ fll_param->clk_ref_div << NAU8825_FLL_REF_DIV_SFT); - /* select divided VCO input */ - regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5, - NAU8825_FLL_FILTER_SW_MASK, 0x0000); -diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h -index dff8edb83bfd..a0b220726a63 100644 ---- a/sound/soc/codecs/nau8825.h -+++ b/sound/soc/codecs/nau8825.h -@@ -114,7 +114,8 @@ - #define NAU8825_FLL_INTEGER_MASK (0x3ff << 0) - - /* FLL4 (0x07) */ --#define NAU8825_FLL_REF_DIV_MASK (0x3 << 10) -+#define NAU8825_FLL_REF_DIV_SFT 10 -+#define NAU8825_FLL_REF_DIV_MASK (0x3 << NAU8825_FLL_REF_DIV_SFT) - - /* FLL5 (0x08) */ - #define NAU8825_FLL_FILTER_SW_MASK (0x1 << 14) -diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c -index a564759845f9..5a3f544bb3a8 100644 ---- a/sound/soc/codecs/tlv320aic3x.c -+++ b/sound/soc/codecs/tlv320aic3x.c -@@ -126,6 +126,16 @@ static const struct reg_default aic3x_reg[] = { - { 108, 0x00 }, { 109, 0x00 }, - }; - -+static bool aic3x_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case AIC3X_RESET: -+ return true; -+ default: -+ return false; -+ } -+} -+ - static const struct regmap_config aic3x_regmap = { - .reg_bits = 8, - .val_bits = 8, -@@ -133,6 +143,9 @@ static const struct regmap_config aic3x_regmap = { - .max_register = DAC_ICC_ADJ, - .reg_defaults = aic3x_reg, - .num_reg_defaults = ARRAY_SIZE(aic3x_reg), -+ -+ .volatile_reg = aic3x_volatile_reg, -+ - .cache_type = REGCACHE_RBTREE, - }; - -diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c -index 65b936e251ea..a1e605bbc465 100644 ---- a/sound/soc/soc-pcm.c -+++ b/sound/soc/soc-pcm.c -@@ -2073,9 +2073,11 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: -- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; - break; -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; -+ break; - } - - out: -diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c -index be1f511e4f54..ae2981460cd8 100644 ---- a/sound/usb/endpoint.c -+++ b/sound/usb/endpoint.c -@@ -384,6 +384,9 @@ static void snd_complete_urb(struct urb *urb) - if (unlikely(atomic_read(&ep->chip->shutdown))) - goto exit_clear; - -+ if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags))) -+ goto exit_clear; -+ - if (usb_pipeout(ep->pipe)) { - retire_outbound_urb(ep, ctx); - /* can be stopped during retire callback */ -diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c -index f1ce60065258..ec30c2fcbac0 100644 ---- a/tools/lib/traceevent/plugin_sched_switch.c -+++ b/tools/lib/traceevent/plugin_sched_switch.c -@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s, - trace_seq_printf(s, "%lld ", val); - - if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) -- trace_seq_printf(s, "[%lld] ", val); -+ trace_seq_printf(s, "[%d] ", (int) val); - - if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0) - write_state(s, val); -@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s, - trace_seq_printf(s, "%lld", val); - - if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0) -- trace_seq_printf(s, " [%lld]", val); -+ trace_seq_printf(s, " [%d]", (int) val); - - return 0; - } -diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf -index 929a32ba15f5..b67e006d56cc 100644 ---- a/tools/perf/Makefile.perf -+++ b/tools/perf/Makefile.perf -@@ -563,9 +563,9 @@ install-tests: all install-gtk - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ - $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' - --install-bin: install-tools install-tests -+install-bin: install-tools install-tests install-traceevent-plugins - --install: install-bin try-install-man install-traceevent-plugins -+install: install-bin try-install-man - - install-python_ext: - $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -index 67282a759496..eeeae0629ad3 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c -@@ -110,6 +110,7 @@ struct intel_pt_decoder { - bool have_tma; - bool have_cyc; - bool fixup_last_mtc; -+ bool have_last_ip; - uint64_t pos; - uint64_t last_ip; - uint64_t ip; -@@ -145,8 +146,6 @@ struct intel_pt_decoder { - bool have_calc_cyc_to_tsc; - int exec_mode; - unsigned int insn_bytes; -- uint64_t sign_bit; -- uint64_t sign_bits; - uint64_t period; - enum intel_pt_period_type period_type; - uint64_t tot_insn_cnt; -@@ -214,9 +213,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) - decoder->data = params->data; - decoder->return_compression = params->return_compression; - -- decoder->sign_bit = (uint64_t)1 << 47; -- decoder->sign_bits = ~(((uint64_t)1 << 48) - 1); -- - decoder->period = params->period; - decoder->period_type = params->period_type; - -@@ -385,21 +381,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen) - return 0; - } - --static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, -- const struct intel_pt_pkt *packet, -+static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet, - uint64_t last_ip) - { - uint64_t ip; - - switch (packet->count) { -- case 2: -+ case 1: - ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) | - packet->payload; - break; -- case 4: -+ case 2: - ip = (last_ip & (uint64_t)0xffffffff00000000ULL) | - packet->payload; - break; -+ case 3: -+ ip = packet->payload; -+ /* Sign-extend 6-byte ip */ -+ if (ip & (uint64_t)0x800000000000ULL) -+ ip |= (uint64_t)0xffff000000000000ULL; -+ break; -+ case 4: -+ ip = (last_ip & (uint64_t)0xffff000000000000ULL) | -+ packet->payload; -+ break; - case 6: - ip = packet->payload; - break; -@@ -407,16 +412,13 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, - return 0; - } - -- if (ip & decoder->sign_bit) -- return ip | decoder->sign_bits; -- - return ip; - } - - static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) - { -- decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet, -- decoder->last_ip); -+ decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip); -+ decoder->have_last_ip = true; - } - - static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) -@@ -1436,7 +1438,8 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) - - case INTEL_PT_FUP: - decoder->pge = true; -- intel_pt_set_last_ip(decoder); -+ if (decoder->packet.count) -+ intel_pt_set_last_ip(decoder); - break; - - case INTEL_PT_MODE_TSX: -@@ -1640,6 +1643,8 @@ next: - break; - - case INTEL_PT_PSB: -+ decoder->last_ip = 0; -+ decoder->have_last_ip = true; - intel_pt_clear_stack(&decoder->stack); - err = intel_pt_walk_psbend(decoder); - if (err == -EAGAIN) -@@ -1718,6 +1723,13 @@ next: - } - } - -+static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder) -+{ -+ return decoder->packet.count && -+ (decoder->have_last_ip || decoder->packet.count == 3 || -+ decoder->packet.count == 6); -+} -+ - /* Walk PSB+ packets to get in sync. */ - static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) - { -@@ -1739,8 +1751,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) - - case INTEL_PT_FUP: - decoder->pge = true; -- if (decoder->last_ip || decoder->packet.count == 6 || -- decoder->packet.count == 0) { -+ if (intel_pt_have_ip(decoder)) { - uint64_t current_ip = decoder->ip; - - intel_pt_set_ip(decoder); -@@ -1832,24 +1843,17 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) - case INTEL_PT_TIP_PGE: - case INTEL_PT_TIP: - decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; -- if (decoder->last_ip || decoder->packet.count == 6 || -- decoder->packet.count == 0) -+ if (intel_pt_have_ip(decoder)) - intel_pt_set_ip(decoder); - if (decoder->ip) - return 0; - break; - - case INTEL_PT_FUP: -- if (decoder->overflow) { -- if (decoder->last_ip || -- decoder->packet.count == 6 || -- decoder->packet.count == 0) -- intel_pt_set_ip(decoder); -- if (decoder->ip) -- return 0; -- } -- if (decoder->packet.count) -- intel_pt_set_last_ip(decoder); -+ if (intel_pt_have_ip(decoder)) -+ intel_pt_set_ip(decoder); -+ if (decoder->ip) -+ return 0; - break; - - case INTEL_PT_MTC: -@@ -1898,6 +1902,8 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) - break; - - case INTEL_PT_PSB: -+ decoder->last_ip = 0; -+ decoder->have_last_ip = true; - intel_pt_clear_stack(&decoder->stack); - err = intel_pt_walk_psb(decoder); - if (err) -@@ -2034,6 +2040,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) - - decoder->pge = false; - decoder->continuous_period = false; -+ decoder->have_last_ip = false; - decoder->last_ip = 0; - decoder->ip = 0; - intel_pt_clear_stack(&decoder->stack); -@@ -2042,6 +2049,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) - if (err) - return err; - -+ decoder->have_last_ip = true; - decoder->pkt_state = INTEL_PT_STATE_NO_IP; - - err = intel_pt_walk_psb(decoder); -@@ -2084,6 +2092,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) - err = intel_pt_sync(decoder); - break; - case INTEL_PT_STATE_NO_IP: -+ decoder->have_last_ip = false; - decoder->last_ip = 0; - decoder->ip = 0; - /* Fall through */ -diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -index 9b2fce25162b..7528ae4f7e28 100644 ---- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c -@@ -293,36 +293,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, - const unsigned char *buf, size_t len, - struct intel_pt_pkt *packet) - { -- switch (byte >> 5) { -+ int ip_len; -+ -+ packet->count = byte >> 5; -+ -+ switch (packet->count) { - case 0: -- packet->count = 0; -+ ip_len = 0; - break; - case 1: - if (len < 3) - return INTEL_PT_NEED_MORE_BYTES; -- packet->count = 2; -+ ip_len = 2; - packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); - break; - case 2: - if (len < 5) - return INTEL_PT_NEED_MORE_BYTES; -- packet->count = 4; -+ ip_len = 4; - packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); - break; - case 3: -- case 6: -+ case 4: - if (len < 7) - return INTEL_PT_NEED_MORE_BYTES; -- packet->count = 6; -+ ip_len = 6; - memcpy_le64(&packet->payload, buf + 1, 6); - break; -+ case 6: -+ if (len < 9) -+ return INTEL_PT_NEED_MORE_BYTES; -+ ip_len = 8; -+ packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); -+ break; - default: - return INTEL_PT_BAD_PACKET; - } - - packet->type = type; - -- return packet->count + 1; -+ return ip_len + 1; - } - - static int intel_pt_get_mode(const unsigned char *buf, size_t len, -diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c -index 27ae382feb2d..7c97ecaeae48 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -488,6 +488,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) - break; - } else { - int n = namesz + descsz; -+ -+ if (n > (int)sizeof(bf)) { -+ n = sizeof(bf); -+ pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n", -+ __func__, filename, nhdr.n_namesz, nhdr.n_descsz); -+ } - if (read(fd, bf, n) != n) - break; - } diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.80-81.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.80-81.patch deleted file mode 100644 index 952c856e9..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.80-81.patch +++ /dev/null @@ -1,2112 +0,0 @@ -diff --git a/Makefile b/Makefile -index dddd55adde24..d049e53a6960 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 80 -+SUBLEVEL = 81 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/armada-388-gp.dts b/arch/arm/boot/dts/armada-388-gp.dts -index cd316021d6ce..6c1b45c1af66 100644 ---- a/arch/arm/boot/dts/armada-388-gp.dts -+++ b/arch/arm/boot/dts/armada-388-gp.dts -@@ -89,7 +89,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pca0_pins>; - interrupt-parent = <&gpio0>; -- interrupts = <18 IRQ_TYPE_EDGE_FALLING>; -+ interrupts = <18 IRQ_TYPE_LEVEL_LOW>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -101,7 +101,7 @@ - compatible = "nxp,pca9555"; - pinctrl-names = "default"; - interrupt-parent = <&gpio0>; -- interrupts = <18 IRQ_TYPE_EDGE_FALLING>; -+ interrupts = <18 IRQ_TYPE_LEVEL_LOW>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h -index bfe2a2f5a644..22b73112b75f 100644 ---- a/arch/arm/include/asm/ftrace.h -+++ b/arch/arm/include/asm/ftrace.h -@@ -54,6 +54,24 @@ static inline void *return_address(unsigned int level) - - #define ftrace_return_address(n) return_address(n) - -+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME -+ -+static inline bool arch_syscall_match_sym_name(const char *sym, -+ const char *name) -+{ -+ if (!strcmp(sym, "sys_mmap2")) -+ sym = "sys_mmap_pgoff"; -+ else if (!strcmp(sym, "sys_statfs64_wrapper")) -+ sym = "sys_statfs64"; -+ else if (!strcmp(sym, "sys_fstatfs64_wrapper")) -+ sym = "sys_fstatfs64"; -+ else if (!strcmp(sym, "sys_arm_fadvise64_64")) -+ sym = "sys_fadvise64_64"; -+ -+ /* Ignore case since sym may start with "SyS" instead of "sys" */ -+ return !strcasecmp(sym, name); -+} -+ - #endif /* ifndef __ASSEMBLY__ */ - - #endif /* _ASM_ARM_FTRACE */ -diff --git a/arch/sparc/include/asm/trap_block.h b/arch/sparc/include/asm/trap_block.h -index ec9c04de3664..ff05992dae7a 100644 ---- a/arch/sparc/include/asm/trap_block.h -+++ b/arch/sparc/include/asm/trap_block.h -@@ -54,6 +54,7 @@ extern struct trap_per_cpu trap_block[NR_CPUS]; - void init_cur_cpu_trap(struct thread_info *); - void setup_tba(void); - extern int ncpus_probed; -+extern u64 cpu_mondo_counter[NR_CPUS]; - - unsigned long real_hard_smp_processor_id(void); - -diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c -index 95a9fa0d2195..4511caa3b7e9 100644 ---- a/arch/sparc/kernel/smp_64.c -+++ b/arch/sparc/kernel/smp_64.c -@@ -617,22 +617,48 @@ retry: - } - } - --/* Multi-cpu list version. */ -+#define CPU_MONDO_COUNTER(cpuid) (cpu_mondo_counter[cpuid]) -+#define MONDO_USEC_WAIT_MIN 2 -+#define MONDO_USEC_WAIT_MAX 100 -+#define MONDO_RETRY_LIMIT 500000 -+ -+/* Multi-cpu list version. -+ * -+ * Deliver xcalls to 'cnt' number of cpus in 'cpu_list'. -+ * Sometimes not all cpus receive the mondo, requiring us to re-send -+ * the mondo until all cpus have received, or cpus are truly stuck -+ * unable to receive mondo, and we timeout. -+ * Occasionally a target cpu strand is borrowed briefly by hypervisor to -+ * perform guest service, such as PCIe error handling. Consider the -+ * service time, 1 second overall wait is reasonable for 1 cpu. -+ * Here two in-between mondo check wait time are defined: 2 usec for -+ * single cpu quick turn around and up to 100usec for large cpu count. -+ * Deliver mondo to large number of cpus could take longer, we adjusts -+ * the retry count as long as target cpus are making forward progress. -+ */ - static void hypervisor_xcall_deliver(struct trap_per_cpu *tb, int cnt) - { -- int retries, this_cpu, prev_sent, i, saw_cpu_error; -+ int this_cpu, tot_cpus, prev_sent, i, rem; -+ int usec_wait, retries, tot_retries; -+ u16 first_cpu = 0xffff; -+ unsigned long xc_rcvd = 0; - unsigned long status; -+ int ecpuerror_id = 0; -+ int enocpu_id = 0; - u16 *cpu_list; -+ u16 cpu; - - this_cpu = smp_processor_id(); -- - cpu_list = __va(tb->cpu_list_pa); -- -- saw_cpu_error = 0; -- retries = 0; -+ usec_wait = cnt * MONDO_USEC_WAIT_MIN; -+ if (usec_wait > MONDO_USEC_WAIT_MAX) -+ usec_wait = MONDO_USEC_WAIT_MAX; -+ retries = tot_retries = 0; -+ tot_cpus = cnt; - prev_sent = 0; -+ - do { -- int forward_progress, n_sent; -+ int n_sent, mondo_delivered, target_cpu_busy; - - status = sun4v_cpu_mondo_send(cnt, - tb->cpu_list_pa, -@@ -640,94 +666,113 @@ static void hypervisor_xcall_deliver(struct trap_per_cpu *tb, int cnt) - - /* HV_EOK means all cpus received the xcall, we're done. */ - if (likely(status == HV_EOK)) -- break; -+ goto xcall_done; -+ -+ /* If not these non-fatal errors, panic */ -+ if (unlikely((status != HV_EWOULDBLOCK) && -+ (status != HV_ECPUERROR) && -+ (status != HV_ENOCPU))) -+ goto fatal_errors; - - /* First, see if we made any forward progress. -+ * -+ * Go through the cpu_list, count the target cpus that have -+ * received our mondo (n_sent), and those that did not (rem). -+ * Re-pack cpu_list with the cpus remain to be retried in the -+ * front - this simplifies tracking the truly stalled cpus. - * - * The hypervisor indicates successful sends by setting - * cpu list entries to the value 0xffff. -+ * -+ * EWOULDBLOCK means some target cpus did not receive the -+ * mondo and retry usually helps. -+ * -+ * ECPUERROR means at least one target cpu is in error state, -+ * it's usually safe to skip the faulty cpu and retry. -+ * -+ * ENOCPU means one of the target cpu doesn't belong to the -+ * domain, perhaps offlined which is unexpected, but not -+ * fatal and it's okay to skip the offlined cpu. - */ -+ rem = 0; - n_sent = 0; - for (i = 0; i < cnt; i++) { -- if (likely(cpu_list[i] == 0xffff)) -+ cpu = cpu_list[i]; -+ if (likely(cpu == 0xffff)) { - n_sent++; -+ } else if ((status == HV_ECPUERROR) && -+ (sun4v_cpu_state(cpu) == HV_CPU_STATE_ERROR)) { -+ ecpuerror_id = cpu + 1; -+ } else if (status == HV_ENOCPU && !cpu_online(cpu)) { -+ enocpu_id = cpu + 1; -+ } else { -+ cpu_list[rem++] = cpu; -+ } - } - -- forward_progress = 0; -- if (n_sent > prev_sent) -- forward_progress = 1; -+ /* No cpu remained, we're done. */ -+ if (rem == 0) -+ break; - -- prev_sent = n_sent; -+ /* Otherwise, update the cpu count for retry. */ -+ cnt = rem; - -- /* If we get a HV_ECPUERROR, then one or more of the cpus -- * in the list are in error state. Use the cpu_state() -- * hypervisor call to find out which cpus are in error state. -+ /* Record the overall number of mondos received by the -+ * first of the remaining cpus. - */ -- if (unlikely(status == HV_ECPUERROR)) { -- for (i = 0; i < cnt; i++) { -- long err; -- u16 cpu; -+ if (first_cpu != cpu_list[0]) { -+ first_cpu = cpu_list[0]; -+ xc_rcvd = CPU_MONDO_COUNTER(first_cpu); -+ } - -- cpu = cpu_list[i]; -- if (cpu == 0xffff) -- continue; -+ /* Was any mondo delivered successfully? */ -+ mondo_delivered = (n_sent > prev_sent); -+ prev_sent = n_sent; - -- err = sun4v_cpu_state(cpu); -- if (err == HV_CPU_STATE_ERROR) { -- saw_cpu_error = (cpu + 1); -- cpu_list[i] = 0xffff; -- } -- } -- } else if (unlikely(status != HV_EWOULDBLOCK)) -- goto fatal_mondo_error; -+ /* or, was any target cpu busy processing other mondos? */ -+ target_cpu_busy = (xc_rcvd < CPU_MONDO_COUNTER(first_cpu)); -+ xc_rcvd = CPU_MONDO_COUNTER(first_cpu); - -- /* Don't bother rewriting the CPU list, just leave the -- * 0xffff and non-0xffff entries in there and the -- * hypervisor will do the right thing. -- * -- * Only advance timeout state if we didn't make any -- * forward progress. -+ /* Retry count is for no progress. If we're making progress, -+ * reset the retry count. - */ -- if (unlikely(!forward_progress)) { -- if (unlikely(++retries > 10000)) -- goto fatal_mondo_timeout; -- -- /* Delay a little bit to let other cpus catch up -- * on their cpu mondo queue work. -- */ -- udelay(2 * cnt); -+ if (likely(mondo_delivered || target_cpu_busy)) { -+ tot_retries += retries; -+ retries = 0; -+ } else if (unlikely(retries > MONDO_RETRY_LIMIT)) { -+ goto fatal_mondo_timeout; - } -- } while (1); - -- if (unlikely(saw_cpu_error)) -- goto fatal_mondo_cpu_error; -+ /* Delay a little bit to let other cpus catch up on -+ * their cpu mondo queue work. -+ */ -+ if (!mondo_delivered) -+ udelay(usec_wait); - -- return; -+ retries++; -+ } while (1); - --fatal_mondo_cpu_error: -- printk(KERN_CRIT "CPU[%d]: SUN4V mondo cpu error, some target cpus " -- "(including %d) were in error state\n", -- this_cpu, saw_cpu_error - 1); -+xcall_done: -+ if (unlikely(ecpuerror_id > 0)) { -+ pr_crit("CPU[%d]: SUN4V mondo cpu error, target cpu(%d) was in error state\n", -+ this_cpu, ecpuerror_id - 1); -+ } else if (unlikely(enocpu_id > 0)) { -+ pr_crit("CPU[%d]: SUN4V mondo cpu error, target cpu(%d) does not belong to the domain\n", -+ this_cpu, enocpu_id - 1); -+ } - return; - -+fatal_errors: -+ /* fatal errors include bad alignment, etc */ -+ pr_crit("CPU[%d]: Args were cnt(%d) cpulist_pa(%lx) mondo_block_pa(%lx)\n", -+ this_cpu, tot_cpus, tb->cpu_list_pa, tb->cpu_mondo_block_pa); -+ panic("Unexpected SUN4V mondo error %lu\n", status); -+ - fatal_mondo_timeout: -- printk(KERN_CRIT "CPU[%d]: SUN4V mondo timeout, no forward " -- " progress after %d retries.\n", -- this_cpu, retries); -- goto dump_cpu_list_and_out; -- --fatal_mondo_error: -- printk(KERN_CRIT "CPU[%d]: Unexpected SUN4V mondo error %lu\n", -- this_cpu, status); -- printk(KERN_CRIT "CPU[%d]: Args were cnt(%d) cpulist_pa(%lx) " -- "mondo_block_pa(%lx)\n", -- this_cpu, cnt, tb->cpu_list_pa, tb->cpu_mondo_block_pa); -- --dump_cpu_list_and_out: -- printk(KERN_CRIT "CPU[%d]: CPU list [ ", this_cpu); -- for (i = 0; i < cnt; i++) -- printk("%u ", cpu_list[i]); -- printk("]\n"); -+ /* some cpus being non-responsive to the cpu mondo */ -+ pr_crit("CPU[%d]: SUN4V mondo timeout, cpu(%d) made no forward progress after %d retries. Total target cpus(%d).\n", -+ this_cpu, first_cpu, (tot_retries + retries), tot_cpus); -+ panic("SUN4V mondo timeout panic\n"); - } - - static void (*xcall_deliver_impl)(struct trap_per_cpu *, int); -diff --git a/arch/sparc/kernel/sun4v_ivec.S b/arch/sparc/kernel/sun4v_ivec.S -index 559bc5e9c199..34631995859a 100644 ---- a/arch/sparc/kernel/sun4v_ivec.S -+++ b/arch/sparc/kernel/sun4v_ivec.S -@@ -26,6 +26,21 @@ sun4v_cpu_mondo: - ldxa [%g0] ASI_SCRATCHPAD, %g4 - sub %g4, TRAP_PER_CPU_FAULT_INFO, %g4 - -+ /* Get smp_processor_id() into %g3 */ -+ sethi %hi(trap_block), %g5 -+ or %g5, %lo(trap_block), %g5 -+ sub %g4, %g5, %g3 -+ srlx %g3, TRAP_BLOCK_SZ_SHIFT, %g3 -+ -+ /* Increment cpu_mondo_counter[smp_processor_id()] */ -+ sethi %hi(cpu_mondo_counter), %g5 -+ or %g5, %lo(cpu_mondo_counter), %g5 -+ sllx %g3, 3, %g3 -+ add %g5, %g3, %g5 -+ ldx [%g5], %g3 -+ add %g3, 1, %g3 -+ stx %g3, [%g5] -+ - /* Get CPU mondo queue base phys address into %g7. */ - ldx [%g4 + TRAP_PER_CPU_CPU_MONDO_PA], %g7 - -diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c -index cc97a43268ee..d883c5951e8b 100644 ---- a/arch/sparc/kernel/traps_64.c -+++ b/arch/sparc/kernel/traps_64.c -@@ -2659,6 +2659,7 @@ void do_getpsr(struct pt_regs *regs) - } - } - -+u64 cpu_mondo_counter[NR_CPUS] = {0}; - struct trap_per_cpu trap_block[NR_CPUS]; - EXPORT_SYMBOL(trap_block); - -diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c -index 318b8465d302..06ceddb3a22e 100644 ---- a/arch/x86/boot/string.c -+++ b/arch/x86/boot/string.c -@@ -14,6 +14,7 @@ - - #include - #include "ctype.h" -+#include "string.h" - - int memcmp(const void *s1, const void *s2, size_t len) - { -diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h -index 725e820602b1..113588ddb43f 100644 ---- a/arch/x86/boot/string.h -+++ b/arch/x86/boot/string.h -@@ -18,4 +18,13 @@ int memcmp(const void *s1, const void *s2, size_t len); - #define memset(d,c,l) __builtin_memset(d,c,l) - #define memcmp __builtin_memcmp - -+extern int strcmp(const char *str1, const char *str2); -+extern int strncmp(const char *cs, const char *ct, size_t count); -+extern size_t strlen(const char *s); -+extern char *strstr(const char *s1, const char *s2); -+extern size_t strnlen(const char *s, size_t maxlen); -+extern unsigned int atou(const char *s); -+extern unsigned long long simple_strtoull(const char *cp, char **endp, -+ unsigned int base); -+ - #endif /* BOOT_STRING_H */ -diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c -index cec49ecf5f31..32187f8a49b4 100644 ---- a/arch/x86/kernel/kvm.c -+++ b/arch/x86/kernel/kvm.c -@@ -151,6 +151,8 @@ void kvm_async_pf_task_wait(u32 token) - if (hlist_unhashed(&n.link)) - break; - -+ rcu_irq_exit(); -+ - if (!n.halted) { - local_irq_enable(); - schedule(); -@@ -159,11 +161,11 @@ void kvm_async_pf_task_wait(u32 token) - /* - * We cannot reschedule. So halt. - */ -- rcu_irq_exit(); - native_safe_halt(); - local_irq_disable(); -- rcu_irq_enter(); - } -+ -+ rcu_irq_enter(); - } - if (!n.halted) - finish_wait(&n.wq, &wait); -diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c -index e417e1a1d02c..5b2aee83d776 100644 ---- a/drivers/ata/libata-scsi.c -+++ b/drivers/ata/libata-scsi.c -@@ -2832,10 +2832,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) - static struct ata_device *ata_find_dev(struct ata_port *ap, int devno) - { - if (!sata_pmp_attached(ap)) { -- if (likely(devno < ata_link_max_devices(&ap->link))) -+ if (likely(devno >= 0 && -+ devno < ata_link_max_devices(&ap->link))) - return &ap->link.device[devno]; - } else { -- if (likely(devno < ap->nr_pmp_links)) -+ if (likely(devno >= 0 && -+ devno < ap->nr_pmp_links)) - return &ap->pmp_link[devno].device[0]; - } - -diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c -index 6ca35495a5be..1e5cd39d0cc2 100644 ---- a/drivers/block/virtio_blk.c -+++ b/drivers/block/virtio_blk.c -@@ -641,11 +641,12 @@ static int virtblk_probe(struct virtio_device *vdev) - if (err) - goto out_put_disk; - -- q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set); -+ q = blk_mq_init_queue(&vblk->tag_set); - if (IS_ERR(q)) { - err = -ENOMEM; - goto out_free_tags; - } -+ vblk->disk->queue = q; - - q->queuedata = vblk; - -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c -index bf4674aa6405..bb9cd35d7fdf 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c -@@ -296,7 +296,7 @@ static int rcar_du_probe(struct platform_device *pdev) - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(rcdu->mmio)) -- ret = PTR_ERR(rcdu->mmio); -+ return PTR_ERR(rcdu->mmio); - - /* DRM/KMS objects */ - ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); -diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c -index 6a81e084593b..2b59d80a09b8 100644 ---- a/drivers/gpu/drm/virtio/virtgpu_fb.c -+++ b/drivers/gpu/drm/virtio/virtgpu_fb.c -@@ -338,7 +338,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper, - info->fbops = &virtio_gpufb_ops; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - -- info->screen_base = obj->vmap; -+ info->screen_buffer = obj->vmap; - info->screen_size = obj->gem_base.size; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); - drm_fb_helper_fill_var(info, &vfbdev->helper, -diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c -index b0edb66a291b..0b7f5a701c60 100644 ---- a/drivers/infiniband/ulp/isert/ib_isert.c -+++ b/drivers/infiniband/ulp/isert/ib_isert.c -@@ -1581,7 +1581,7 @@ isert_rcv_completion(struct iser_rx_desc *desc, - struct isert_conn *isert_conn, - u32 xfer_len) - { -- struct ib_device *ib_dev = isert_conn->cm_id->device; -+ struct ib_device *ib_dev = isert_conn->device->ib_device; - struct iscsi_hdr *hdr; - u64 rx_dma; - int rx_buflen; -diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c -index a18fe5d47238..b4857cd7069e 100644 ---- a/drivers/media/pci/saa7164/saa7164-bus.c -+++ b/drivers/media/pci/saa7164/saa7164-bus.c -@@ -393,11 +393,11 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, - msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size); - msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command); - msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector); -+ memcpy(msg, &msg_tmp, sizeof(*msg)); - - /* No need to update the read positions, because this was a peek */ - /* If the caller specifically want to peek, return */ - if (peekonly) { -- memcpy(msg, &msg_tmp, sizeof(*msg)); - goto peekout; - } - -@@ -442,21 +442,15 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, - space_rem = bus->m_dwSizeGetRing - curr_grp; - - if (space_rem < sizeof(*msg)) { -- /* msg wraps around the ring */ -- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem); -- memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing, -- sizeof(*msg) - space_rem); - if (buf) - memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) - - space_rem, buf_size); - - } else if (space_rem == sizeof(*msg)) { -- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); - if (buf) - memcpy_fromio(buf, bus->m_pdwGetRing, buf_size); - } else { - /* Additional data wraps around the ring */ -- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); - if (buf) { - memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + - sizeof(*msg), space_rem - sizeof(*msg)); -@@ -469,15 +463,10 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, - - } else { - /* No wrapping */ -- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg)); - if (buf) - memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg), - buf_size); - } -- /* Convert from little endian to CPU */ -- msg->size = le16_to_cpu((__force __le16)msg->size); -- msg->command = le32_to_cpu((__force __le32)msg->command); -- msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector); - - /* Update the read positions, adjusting the ring */ - saa7164_writel(bus->m_dwGetReadPos, new_grp); -diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c -index 7767e072d623..1f656a3a84b9 100644 ---- a/drivers/media/platform/davinci/vpfe_capture.c -+++ b/drivers/media/platform/davinci/vpfe_capture.c -@@ -1709,27 +1709,9 @@ static long vpfe_param_handler(struct file *file, void *priv, - - switch (cmd) { - case VPFE_CMD_S_CCDC_RAW_PARAMS: -+ ret = -EINVAL; - v4l2_warn(&vpfe_dev->v4l2_dev, -- "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); -- if (ccdc_dev->hw_ops.set_params) { -- ret = ccdc_dev->hw_ops.set_params(param); -- if (ret) { -- v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, -- "Error setting parameters in CCDC\n"); -- goto unlock_out; -- } -- ret = vpfe_get_ccdc_image_format(vpfe_dev, -- &vpfe_dev->fmt); -- if (ret < 0) { -- v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, -- "Invalid image format at CCDC\n"); -- goto unlock_out; -- } -- } else { -- ret = -EINVAL; -- v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, -- "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); -- } -+ "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); - break; - default: - ret = -ENOTTY; -diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c -index a32659fcd266..efc21b1da211 100644 ---- a/drivers/media/rc/ir-lirc-codec.c -+++ b/drivers/media/rc/ir-lirc-codec.c -@@ -254,7 +254,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, - return 0; - - case LIRC_GET_REC_RESOLUTION: -- val = dev->rx_resolution; -+ val = dev->rx_resolution / 1000; - break; - - case LIRC_SET_WIDEBAND_RECEIVER: -diff --git a/drivers/net/ethernet/aurora/nb8800.c b/drivers/net/ethernet/aurora/nb8800.c -index ecc4a334c507..0a54e7dac0ab 100644 ---- a/drivers/net/ethernet/aurora/nb8800.c -+++ b/drivers/net/ethernet/aurora/nb8800.c -@@ -608,7 +608,7 @@ static void nb8800_mac_config(struct net_device *dev) - mac_mode |= HALF_DUPLEX; - - if (gigabit) { -- if (priv->phy_mode == PHY_INTERFACE_MODE_RGMII) -+ if (phy_interface_is_rgmii(dev->phydev)) - mac_mode |= RGMII_MODE; - - mac_mode |= GMAC_MODE; -@@ -1295,11 +1295,10 @@ static int nb8800_tangox_init(struct net_device *dev) - break; - - case PHY_INTERFACE_MODE_RGMII: -- pad_mode = PAD_MODE_RGMII; -- break; -- -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: -- pad_mode = PAD_MODE_RGMII | PAD_MODE_GTX_CLK_DELAY; -+ pad_mode = PAD_MODE_RGMII; - break; - - default: -diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c -index 21e5b9ed1ead..3613469dc5c6 100644 ---- a/drivers/net/ethernet/broadcom/tg3.c -+++ b/drivers/net/ethernet/broadcom/tg3.c -@@ -8722,11 +8722,14 @@ static void tg3_free_consistent(struct tg3 *tp) - tg3_mem_rx_release(tp); - tg3_mem_tx_release(tp); - -+ /* Protect tg3_get_stats64() from reading freed tp->hw_stats. */ -+ tg3_full_lock(tp, 0); - if (tp->hw_stats) { - dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats), - tp->hw_stats, tp->stats_mapping); - tp->hw_stats = NULL; - } -+ tg3_full_unlock(tp); - } - - /* -diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -index cc199063612a..6c66d2979795 100644 ---- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c -@@ -630,6 +630,10 @@ static void dump_command(struct mlx5_core_dev *dev, - pr_debug("\n"); - } - -+static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); -+static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, -+ struct mlx5_cmd_msg *msg); -+ - static void cmd_work_handler(struct work_struct *work) - { - struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); -@@ -638,16 +642,27 @@ static void cmd_work_handler(struct work_struct *work) - struct mlx5_cmd_layout *lay; - struct semaphore *sem; - unsigned long flags; -+ int alloc_ret; - - sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; - down(sem); - if (!ent->page_queue) { -- ent->idx = alloc_ent(cmd); -- if (ent->idx < 0) { -+ alloc_ret = alloc_ent(cmd); -+ if (alloc_ret < 0) { -+ if (ent->callback) { -+ ent->callback(-EAGAIN, ent->context); -+ mlx5_free_cmd_msg(dev, ent->out); -+ free_msg(dev, ent->in); -+ free_cmd(ent); -+ } else { -+ ent->ret = -EAGAIN; -+ complete(&ent->done); -+ } - mlx5_core_err(dev, "failed to allocate command entry\n"); - up(sem); - return; - } -+ ent->idx = alloc_ret; - } else { - ent->idx = cmd->max_reg_cmds; - spin_lock_irqsave(&cmd->alloc_lock, flags); -diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c -index 4296066a7ad3..479af106aaeb 100644 ---- a/drivers/net/ethernet/renesas/sh_eth.c -+++ b/drivers/net/ethernet/renesas/sh_eth.c -@@ -819,6 +819,7 @@ static struct sh_eth_cpu_data r8a7740_data = { - .rpadir_value = 2 << 16, - .no_trimd = 1, - .no_ade = 1, -+ .hw_crc = 1, - .tsu = 1, - .select_mii = 1, - .shift_rd0 = 1, -diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c -index bca6a1e72d1d..e1bb802d4a4d 100644 ---- a/drivers/net/irda/mcs7780.c -+++ b/drivers/net/irda/mcs7780.c -@@ -141,9 +141,19 @@ static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val) - static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) - { - struct usb_device *dev = mcs->usbdev; -- int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, -- MCS_RD_RTYPE, 0, reg, val, 2, -- msecs_to_jiffies(MCS_CTRL_TIMEOUT)); -+ void *dmabuf; -+ int ret; -+ -+ dmabuf = kmalloc(sizeof(__u16), GFP_KERNEL); -+ if (!dmabuf) -+ return -ENOMEM; -+ -+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, -+ MCS_RD_RTYPE, 0, reg, dmabuf, 2, -+ msecs_to_jiffies(MCS_CTRL_TIMEOUT)); -+ -+ memcpy(val, dmabuf, sizeof(__u16)); -+ kfree(dmabuf); - - return ret; - } -diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c -index 32f10662f4ac..7242dd4b3238 100644 ---- a/drivers/net/phy/dp83867.c -+++ b/drivers/net/phy/dp83867.c -@@ -29,6 +29,7 @@ - #define MII_DP83867_MICR 0x12 - #define MII_DP83867_ISR 0x13 - #define DP83867_CTRL 0x1f -+#define DP83867_CFG3 0x1e - - /* Extended Registers */ - #define DP83867_RGMIICTL 0x0032 -@@ -89,6 +90,8 @@ static int dp83867_config_intr(struct phy_device *phydev) - micr_status |= - (MII_DP83867_MICR_AN_ERR_INT_EN | - MII_DP83867_MICR_SPEED_CHNG_INT_EN | -+ MII_DP83867_MICR_AUTONEG_COMP_INT_EN | -+ MII_DP83867_MICR_LINK_STS_CHNG_INT_EN | - MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN | - MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN); - -@@ -184,6 +187,13 @@ static int dp83867_config_init(struct phy_device *phydev) - DP83867_DEVADDR, phydev->addr, delay); - } - -+ /* Enable Interrupt output INT_OE in CFG3 register */ -+ if (phy_interrupt_is_valid(phydev)) { -+ val = phy_read(phydev, DP83867_CFG3); -+ val |= BIT(7); -+ phy_write(phydev, DP83867_CFG3, val); -+ } -+ - return 0; - } - -diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c -index 851c0e121807..49d9f0a789fe 100644 ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -541,6 +541,9 @@ void phy_stop_machine(struct phy_device *phydev) - if (phydev->state > PHY_UP && phydev->state != PHY_HALTED) - phydev->state = PHY_UP; - mutex_unlock(&phydev->lock); -+ -+ /* Now we can run the state machine synchronously */ -+ phy_state_machine(&phydev->state_queue.work); - } - - /** -@@ -918,6 +921,15 @@ void phy_state_machine(struct work_struct *work) - if (old_link != phydev->link) - phydev->state = PHY_CHANGELINK; - } -+ /* -+ * Failsafe: check that nobody set phydev->link=0 between two -+ * poll cycles, otherwise we won't leave RUNNING state as long -+ * as link remains down. -+ */ -+ if (!phydev->link && phydev->state == PHY_RUNNING) { -+ phydev->state = PHY_CHANGELINK; -+ dev_err(&phydev->dev, "no link in PHY_RUNNING\n"); -+ } - break; - case PHY_CHANGELINK: - err = phy_read_status(phydev); -diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c -index 1d1e5f7723ab..8179727d3423 100644 ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -1368,6 +1368,8 @@ static int phy_remove(struct device *dev) - { - struct phy_device *phydev = to_phy_device(dev); - -+ cancel_delayed_work_sync(&phydev->state_queue); -+ - mutex_lock(&phydev->lock); - phydev->state = PHY_DOWN; - mutex_unlock(&phydev->lock); -diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h -index 0333ab0fd926..34173b5e886f 100644 ---- a/drivers/net/xen-netback/common.h -+++ b/drivers/net/xen-netback/common.h -@@ -201,6 +201,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */ - unsigned long remaining_credit; - struct timer_list credit_timeout; - u64 credit_window_start; -+ bool rate_limited; - - /* Statistics */ - struct xenvif_stats stats; -diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c -index e7bd63eb2876..60b26f32d31d 100644 ---- a/drivers/net/xen-netback/interface.c -+++ b/drivers/net/xen-netback/interface.c -@@ -105,7 +105,11 @@ static int xenvif_poll(struct napi_struct *napi, int budget) - - if (work_done < budget) { - napi_complete(napi); -- xenvif_napi_schedule_or_enable_events(queue); -+ /* If the queue is rate-limited, it shall be -+ * rescheduled in the timer callback. -+ */ -+ if (likely(!queue->rate_limited)) -+ xenvif_napi_schedule_or_enable_events(queue); - } - - return work_done; -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index 1049c34e7d43..72ee1c305cc4 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -687,6 +687,7 @@ static void tx_add_credit(struct xenvif_queue *queue) - max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */ - - queue->remaining_credit = min(max_credit, max_burst); -+ queue->rate_limited = false; - } - - void xenvif_tx_credit_callback(unsigned long data) -@@ -1184,8 +1185,10 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) - msecs_to_jiffies(queue->credit_usec / 1000); - - /* Timer could already be pending in rare cases. */ -- if (timer_pending(&queue->credit_timeout)) -+ if (timer_pending(&queue->credit_timeout)) { -+ queue->rate_limited = true; - return true; -+ } - - /* Passed the point where we can replenish credit? */ - if (time_after_eq64(now, next_credit)) { -@@ -1200,6 +1203,7 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) - mod_timer(&queue->credit_timeout, - next_credit); - queue->credit_window_start = next_credit; -+ queue->rate_limited = true; - - return true; - } -diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c -index 6b942d9e5b74..1ed85dfc008d 100644 ---- a/drivers/scsi/qla2xxx/qla_attr.c -+++ b/drivers/scsi/qla2xxx/qla_attr.c -@@ -329,12 +329,15 @@ qla2x00_sysfs_read_optrom(struct file *filp, struct kobject *kobj, - struct qla_hw_data *ha = vha->hw; - ssize_t rval = 0; - -+ mutex_lock(&ha->optrom_mutex); -+ - if (ha->optrom_state != QLA_SREADING) -- return 0; -+ goto out; - -- mutex_lock(&ha->optrom_mutex); - rval = memory_read_from_buffer(buf, count, &off, ha->optrom_buffer, - ha->optrom_region_size); -+ -+out: - mutex_unlock(&ha->optrom_mutex); - - return rval; -@@ -349,14 +352,19 @@ qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj, - struct device, kobj))); - struct qla_hw_data *ha = vha->hw; - -- if (ha->optrom_state != QLA_SWRITING) -+ mutex_lock(&ha->optrom_mutex); -+ -+ if (ha->optrom_state != QLA_SWRITING) { -+ mutex_unlock(&ha->optrom_mutex); - return -EINVAL; -- if (off > ha->optrom_region_size) -+ } -+ if (off > ha->optrom_region_size) { -+ mutex_unlock(&ha->optrom_mutex); - return -ERANGE; -+ } - if (off + count > ha->optrom_region_size) - count = ha->optrom_region_size - off; - -- mutex_lock(&ha->optrom_mutex); - memcpy(&ha->optrom_buffer[off], buf, count); - mutex_unlock(&ha->optrom_mutex); - -diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c -index a180c000e246..31d5d9c0e10b 100644 ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -3965,6 +3965,8 @@ int iscsi_target_tx_thread(void *arg) - { - int ret = 0; - struct iscsi_conn *conn = arg; -+ bool conn_freed = false; -+ - /* - * Allow ourselves to be interrupted by SIGINT so that a - * connection recovery / failure event can be triggered externally. -@@ -3990,12 +3992,14 @@ get_immediate: - goto transport_err; - - ret = iscsit_handle_response_queue(conn); -- if (ret == 1) -+ if (ret == 1) { - goto get_immediate; -- else if (ret == -ECONNRESET) -+ } else if (ret == -ECONNRESET) { -+ conn_freed = true; - goto out; -- else if (ret < 0) -+ } else if (ret < 0) { - goto transport_err; -+ } - } - - transport_err: -@@ -4005,8 +4009,13 @@ transport_err: - * responsible for cleaning up the early connection failure. - */ - if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) -- iscsit_take_action_for_connection_exit(conn); -+ iscsit_take_action_for_connection_exit(conn, &conn_freed); - out: -+ if (!conn_freed) { -+ while (!kthread_should_stop()) { -+ msleep(100); -+ } -+ } - return 0; - } - -@@ -4105,6 +4114,7 @@ int iscsi_target_rx_thread(void *arg) - u32 checksum = 0, digest = 0; - struct iscsi_conn *conn = arg; - struct kvec iov; -+ bool conn_freed = false; - /* - * Allow ourselves to be interrupted by SIGINT so that a - * connection recovery / failure event can be triggered externally. -@@ -4116,7 +4126,7 @@ int iscsi_target_rx_thread(void *arg) - */ - rc = wait_for_completion_interruptible(&conn->rx_login_comp); - if (rc < 0 || iscsi_target_check_conn_state(conn)) -- return 0; -+ goto out; - - if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { - struct completion comp; -@@ -4201,7 +4211,13 @@ int iscsi_target_rx_thread(void *arg) - transport_err: - if (!signal_pending(current)) - atomic_set(&conn->transport_failed, 1); -- iscsit_take_action_for_connection_exit(conn); -+ iscsit_take_action_for_connection_exit(conn, &conn_freed); -+out: -+ if (!conn_freed) { -+ while (!kthread_should_stop()) { -+ msleep(100); -+ } -+ } - return 0; - } - -@@ -4575,8 +4591,11 @@ static void iscsit_logout_post_handler_closesession( - * always sleep waiting for RX/TX thread shutdown to complete - * within iscsit_close_connection(). - */ -- if (conn->conn_transport->transport_type == ISCSI_TCP) -+ if (conn->conn_transport->transport_type == ISCSI_TCP) { - sleep = cmpxchg(&conn->tx_thread_active, true, false); -+ if (!sleep) -+ return; -+ } - - atomic_set(&conn->conn_logout_remove, 0); - complete(&conn->conn_logout_comp); -@@ -4592,8 +4611,11 @@ static void iscsit_logout_post_handler_samecid( - { - int sleep = 1; - -- if (conn->conn_transport->transport_type == ISCSI_TCP) -+ if (conn->conn_transport->transport_type == ISCSI_TCP) { - sleep = cmpxchg(&conn->tx_thread_active, true, false); -+ if (!sleep) -+ return; -+ } - - atomic_set(&conn->conn_logout_remove, 0); - complete(&conn->conn_logout_comp); -diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c -index 210f6e4830e3..6c88fb021444 100644 ---- a/drivers/target/iscsi/iscsi_target_erl0.c -+++ b/drivers/target/iscsi/iscsi_target_erl0.c -@@ -930,8 +930,10 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn) - } - } - --void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) -+void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed) - { -+ *conn_freed = false; -+ - spin_lock_bh(&conn->state_lock); - if (atomic_read(&conn->connection_exit)) { - spin_unlock_bh(&conn->state_lock); -@@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) - if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) { - spin_unlock_bh(&conn->state_lock); - iscsit_close_connection(conn); -+ *conn_freed = true; - return; - } - -@@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) - spin_unlock_bh(&conn->state_lock); - - iscsit_handle_connection_cleanup(conn); -+ *conn_freed = true; - } -diff --git a/drivers/target/iscsi/iscsi_target_erl0.h b/drivers/target/iscsi/iscsi_target_erl0.h -index a9e2f9497fb2..fbc1d84a63c3 100644 ---- a/drivers/target/iscsi/iscsi_target_erl0.h -+++ b/drivers/target/iscsi/iscsi_target_erl0.h -@@ -9,6 +9,6 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *); - extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *); - extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); - extern void iscsit_fall_back_to_erl0(struct iscsi_session *); --extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *); -+extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *); - - #endif /*** ISCSI_TARGET_ERL0_H ***/ -diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c -index 4a137b0ae3dc..b19edffa7d98 100644 ---- a/drivers/target/iscsi/iscsi_target_login.c -+++ b/drivers/target/iscsi/iscsi_target_login.c -@@ -1436,5 +1436,9 @@ int iscsi_target_login_thread(void *arg) - break; - } - -+ while (!kthread_should_stop()) { -+ msleep(100); -+ } -+ - return 0; - } -diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c -index 549a2bbbf4df..58c629aec73c 100644 ---- a/drivers/target/iscsi/iscsi_target_nego.c -+++ b/drivers/target/iscsi/iscsi_target_nego.c -@@ -489,14 +489,60 @@ static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn) - - static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); - --static bool iscsi_target_sk_state_check(struct sock *sk) -+static bool __iscsi_target_sk_check_close(struct sock *sk) - { - if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { -- pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE," -+ pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE," - "returning FALSE\n"); -- return false; -+ return true; - } -- return true; -+ return false; -+} -+ -+static bool iscsi_target_sk_check_close(struct iscsi_conn *conn) -+{ -+ bool state = false; -+ -+ if (conn->sock) { -+ struct sock *sk = conn->sock->sk; -+ -+ read_lock_bh(&sk->sk_callback_lock); -+ state = (__iscsi_target_sk_check_close(sk) || -+ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); -+ read_unlock_bh(&sk->sk_callback_lock); -+ } -+ return state; -+} -+ -+static bool iscsi_target_sk_check_flag(struct iscsi_conn *conn, unsigned int flag) -+{ -+ bool state = false; -+ -+ if (conn->sock) { -+ struct sock *sk = conn->sock->sk; -+ -+ read_lock_bh(&sk->sk_callback_lock); -+ state = test_bit(flag, &conn->login_flags); -+ read_unlock_bh(&sk->sk_callback_lock); -+ } -+ return state; -+} -+ -+static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned int flag) -+{ -+ bool state = false; -+ -+ if (conn->sock) { -+ struct sock *sk = conn->sock->sk; -+ -+ write_lock_bh(&sk->sk_callback_lock); -+ state = (__iscsi_target_sk_check_close(sk) || -+ test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)); -+ if (!state) -+ clear_bit(flag, &conn->login_flags); -+ write_unlock_bh(&sk->sk_callback_lock); -+ } -+ return state; - } - - static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) -@@ -536,6 +582,20 @@ static void iscsi_target_do_login_rx(struct work_struct *work) - - pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", - conn, current->comm, current->pid); -+ /* -+ * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready() -+ * before initial PDU processing in iscsi_target_start_negotiation() -+ * has completed, go ahead and retry until it's cleared. -+ * -+ * Otherwise if the TCP connection drops while this is occuring, -+ * iscsi_target_start_negotiation() will detect the failure, call -+ * cancel_delayed_work_sync(&conn->login_work), and cleanup the -+ * remaining iscsi connection resources from iscsi_np process context. -+ */ -+ if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) { -+ schedule_delayed_work(&conn->login_work, msecs_to_jiffies(10)); -+ return; -+ } - - spin_lock(&tpg->tpg_state_lock); - state = (tpg->tpg_state == TPG_STATE_ACTIVE); -@@ -543,26 +603,12 @@ static void iscsi_target_do_login_rx(struct work_struct *work) - - if (!state) { - pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); -- iscsi_target_restore_sock_callbacks(conn); -- iscsi_target_login_drop(conn, login); -- iscsit_deaccess_np(np, tpg, tpg_np); -- return; -+ goto err; - } - -- if (conn->sock) { -- struct sock *sk = conn->sock->sk; -- -- read_lock_bh(&sk->sk_callback_lock); -- state = iscsi_target_sk_state_check(sk); -- read_unlock_bh(&sk->sk_callback_lock); -- -- if (!state) { -- pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); -- iscsi_target_restore_sock_callbacks(conn); -- iscsi_target_login_drop(conn, login); -- iscsit_deaccess_np(np, tpg, tpg_np); -- return; -- } -+ if (iscsi_target_sk_check_close(conn)) { -+ pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); -+ goto err; - } - - conn->login_kworker = current; -@@ -580,34 +626,29 @@ static void iscsi_target_do_login_rx(struct work_struct *work) - flush_signals(current); - conn->login_kworker = NULL; - -- if (rc < 0) { -- iscsi_target_restore_sock_callbacks(conn); -- iscsi_target_login_drop(conn, login); -- iscsit_deaccess_np(np, tpg, tpg_np); -- return; -- } -+ if (rc < 0) -+ goto err; - - pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", - conn, current->comm, current->pid); - - rc = iscsi_target_do_login(conn, login); - if (rc < 0) { -- iscsi_target_restore_sock_callbacks(conn); -- iscsi_target_login_drop(conn, login); -- iscsit_deaccess_np(np, tpg, tpg_np); -+ goto err; - } else if (!rc) { -- if (conn->sock) { -- struct sock *sk = conn->sock->sk; -- -- write_lock_bh(&sk->sk_callback_lock); -- clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); -- write_unlock_bh(&sk->sk_callback_lock); -- } -+ if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE)) -+ goto err; - } else if (rc == 1) { - iscsi_target_nego_release(conn); - iscsi_post_login_handler(np, conn, zero_tsih); - iscsit_deaccess_np(np, tpg, tpg_np); - } -+ return; -+ -+err: -+ iscsi_target_restore_sock_callbacks(conn); -+ iscsi_target_login_drop(conn, login); -+ iscsit_deaccess_np(np, tpg, tpg_np); - } - - static void iscsi_target_do_cleanup(struct work_struct *work) -@@ -655,31 +696,54 @@ static void iscsi_target_sk_state_change(struct sock *sk) - orig_state_change(sk); - return; - } -+ state = __iscsi_target_sk_check_close(sk); -+ pr_debug("__iscsi_target_sk_close_change: state: %d\n", state); -+ - if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { - pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" - " conn: %p\n", conn); -+ if (state) -+ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); - write_unlock_bh(&sk->sk_callback_lock); - orig_state_change(sk); - return; - } -- if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { -+ if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { - pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n", - conn); - write_unlock_bh(&sk->sk_callback_lock); - orig_state_change(sk); - return; - } -+ /* -+ * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED, -+ * but only queue conn->login_work -> iscsi_target_do_login_rx() -+ * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared. -+ * -+ * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close() -+ * will detect the dropped TCP connection from delayed workqueue context. -+ * -+ * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial -+ * iscsi_target_start_negotiation() is running, iscsi_target_do_login() -+ * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation() -+ * via iscsi_target_sk_check_and_clear() is responsible for detecting the -+ * dropped TCP connection in iscsi_np process context, and cleaning up -+ * the remaining iscsi connection resources. -+ */ -+ if (state) { -+ pr_debug("iscsi_target_sk_state_change got failed state\n"); -+ set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags); -+ state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); -+ write_unlock_bh(&sk->sk_callback_lock); - -- state = iscsi_target_sk_state_check(sk); -- write_unlock_bh(&sk->sk_callback_lock); -- -- pr_debug("iscsi_target_sk_state_change: state: %d\n", state); -+ orig_state_change(sk); - -- if (!state) { -- pr_debug("iscsi_target_sk_state_change got failed state\n"); -- schedule_delayed_work(&conn->login_cleanup_work, 0); -+ if (!state) -+ schedule_delayed_work(&conn->login_work, 0); - return; - } -+ write_unlock_bh(&sk->sk_callback_lock); -+ - orig_state_change(sk); - } - -@@ -944,6 +1008,15 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo - if (iscsi_target_handle_csg_one(conn, login) < 0) - return -1; - if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { -+ /* -+ * Check to make sure the TCP connection has not -+ * dropped asynchronously while session reinstatement -+ * was occuring in this kthread context, before -+ * transitioning to full feature phase operation. -+ */ -+ if (iscsi_target_sk_check_close(conn)) -+ return -1; -+ - login->tsih = conn->sess->tsih; - login->login_complete = 1; - iscsi_target_restore_sock_callbacks(conn); -@@ -970,21 +1043,6 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo - break; - } - -- if (conn->sock) { -- struct sock *sk = conn->sock->sk; -- bool state; -- -- read_lock_bh(&sk->sk_callback_lock); -- state = iscsi_target_sk_state_check(sk); -- read_unlock_bh(&sk->sk_callback_lock); -- -- if (!state) { -- pr_debug("iscsi_target_do_login() failed state for" -- " conn: %p\n", conn); -- return -1; -- } -- } -- - return 0; - } - -@@ -1248,16 +1306,28 @@ int iscsi_target_start_negotiation( - { - int ret; - -+ if (conn->sock) { -+ struct sock *sk = conn->sock->sk; -+ -+ write_lock_bh(&sk->sk_callback_lock); -+ set_bit(LOGIN_FLAGS_READY, &conn->login_flags); -+ set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags); -+ write_unlock_bh(&sk->sk_callback_lock); -+ } -+ /* -+ * If iscsi_target_do_login returns zero to signal more PDU -+ * exchanges are required to complete the login, go ahead and -+ * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection -+ * is still active. -+ * -+ * Otherwise if TCP connection dropped asynchronously, go ahead -+ * and perform connection cleanup now. -+ */ - ret = iscsi_target_do_login(conn, login); -- if (!ret) { -- if (conn->sock) { -- struct sock *sk = conn->sock->sk; -+ if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) -+ ret = -1; - -- write_lock_bh(&sk->sk_callback_lock); -- set_bit(LOGIN_FLAGS_READY, &conn->login_flags); -- write_unlock_bh(&sk->sk_callback_lock); -- } -- } else if (ret < 0) { -+ if (ret < 0) { - cancel_delayed_work_sync(&conn->login_work); - cancel_delayed_work_sync(&conn->login_cleanup_work); - iscsi_target_restore_sock_callbacks(conn); -diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c -index f916d18ccb48..b070ddf1dc37 100644 ---- a/drivers/target/target_core_fabric_configfs.c -+++ b/drivers/target/target_core_fabric_configfs.c -@@ -92,6 +92,11 @@ static int target_fabric_mappedlun_link( - pr_err("Source se_lun->lun_se_dev does not exist\n"); - return -EINVAL; - } -+ if (lun->lun_shutdown) { -+ pr_err("Unable to create mappedlun symlink because" -+ " lun->lun_shutdown=true\n"); -+ return -EINVAL; -+ } - se_tpg = lun->lun_tpg; - - nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; -diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c -index 899c33b3c734..f69f4902dc07 100644 ---- a/drivers/target/target_core_tpg.c -+++ b/drivers/target/target_core_tpg.c -@@ -673,6 +673,8 @@ void core_tpg_remove_lun( - */ - struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev); - -+ lun->lun_shutdown = true; -+ - core_clear_lun_from_tpg(lun, tpg); - /* - * Wait for any active I/O references to percpu se_lun->lun_ref to -@@ -694,6 +696,8 @@ void core_tpg_remove_lun( - } - if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) - hlist_del_rcu(&lun->link); -+ -+ lun->lun_shutdown = false; - mutex_unlock(&tpg->tpg_lun_mutex); - - percpu_ref_exit(&lun->lun_ref); -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 8772bfc3415b..45ef9975caec 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -500,6 +500,8 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, - lastoff = page_offset(page); - bh = head = page_buffers(page); - do { -+ if (lastoff + bh->b_size <= startoff) -+ goto next; - if (buffer_uptodate(bh) || - buffer_unwritten(bh)) { - if (whence == SEEK_DATA) -@@ -514,6 +516,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, - unlock_page(page); - goto out; - } -+next: - lastoff += bh->b_size; - bh = bh->b_this_page; - } while (bh != head); -diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c -index 34038e3598d5..74516efd874c 100644 ---- a/fs/ext4/resize.c -+++ b/fs/ext4/resize.c -@@ -1926,7 +1926,8 @@ retry: - n_desc_blocks = o_desc_blocks + - le16_to_cpu(es->s_reserved_gdt_blocks); - n_group = n_desc_blocks * EXT4_DESC_PER_BLOCK(sb); -- n_blocks_count = n_group * EXT4_BLOCKS_PER_GROUP(sb); -+ n_blocks_count = (ext4_fsblk_t)n_group * -+ EXT4_BLOCKS_PER_GROUP(sb); - n_group--; /* set to last group number */ - } - -diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c -index 86e1cb899957..4f666368aa85 100644 ---- a/fs/f2fs/super.c -+++ b/fs/f2fs/super.c -@@ -1078,6 +1078,8 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi) - unsigned int total, fsmeta; - struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); - struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); -+ unsigned int main_segs, blocks_per_seg; -+ int i; - - total = le32_to_cpu(raw_super->segment_count); - fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); -@@ -1089,6 +1091,20 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi) - if (unlikely(fsmeta >= total)) - return 1; - -+ main_segs = le32_to_cpu(raw_super->segment_count_main); -+ blocks_per_seg = sbi->blocks_per_seg; -+ -+ for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { -+ if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || -+ le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) -+ return 1; -+ } -+ for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { -+ if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || -+ le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) -+ return 1; -+ } -+ - if (unlikely(f2fs_cp_error(sbi))) { - f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck"); - return 1; -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 2ccccbfcd532..36f4695aa604 100644 ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h -@@ -503,6 +503,10 @@ struct mm_struct { - * PROT_NONE or PROT_NUMA mapped page. - */ - bool tlb_flush_pending; -+#endif -+#ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH -+ /* See flush_tlb_batched_pending() */ -+ bool tlb_flush_batched; - #endif - struct uprobes_state uprobes_state; - #ifdef CONFIG_X86_INTEL_MPX -diff --git a/include/linux/sched.h b/include/linux/sched.h -index 352213b360d7..eff7c1fad26f 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -801,6 +801,16 @@ struct signal_struct { - - #define SIGNAL_UNKILLABLE 0x00000040 /* for init: ignore fatal signals */ - -+#define SIGNAL_STOP_MASK (SIGNAL_CLD_MASK | SIGNAL_STOP_STOPPED | \ -+ SIGNAL_STOP_CONTINUED) -+ -+static inline void signal_set_stop_flags(struct signal_struct *sig, -+ unsigned int flags) -+{ -+ WARN_ON(sig->flags & (SIGNAL_GROUP_EXIT|SIGNAL_GROUP_COREDUMP)); -+ sig->flags = (sig->flags & ~SIGNAL_STOP_MASK) | flags; -+} -+ - /* If true, all threads except ->group_exit_task have pending SIGKILL */ - static inline int signal_group_exit(const struct signal_struct *sig) - { -diff --git a/include/linux/slab.h b/include/linux/slab.h -index 2037a861e367..8a2a9ffaf5de 100644 ---- a/include/linux/slab.h -+++ b/include/linux/slab.h -@@ -203,7 +203,7 @@ size_t ksize(const void *); - * (PAGE_SIZE*2). Larger requests are passed to the page allocator. - */ - #define KMALLOC_SHIFT_HIGH (PAGE_SHIFT + 1) --#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT) -+#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) - #ifndef KMALLOC_SHIFT_LOW - #define KMALLOC_SHIFT_LOW 3 - #endif -@@ -216,7 +216,7 @@ size_t ksize(const void *); - * be allocated from the same page. - */ - #define KMALLOC_SHIFT_HIGH PAGE_SHIFT --#define KMALLOC_SHIFT_MAX 30 -+#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) - #ifndef KMALLOC_SHIFT_LOW - #define KMALLOC_SHIFT_LOW 3 - #endif -diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h -index 0197358f1e81..262d5c95dfc8 100644 ---- a/include/linux/workqueue.h -+++ b/include/linux/workqueue.h -@@ -311,6 +311,7 @@ enum { - - __WQ_DRAINING = 1 << 16, /* internal: workqueue is draining */ - __WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */ -+ __WQ_ORDERED_EXPLICIT = 1 << 18, /* internal: alloc_ordered_workqueue() */ - - WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */ - WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */ -@@ -408,7 +409,8 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, - * Pointer to the allocated workqueue on success, %NULL on failure. - */ - #define alloc_ordered_workqueue(fmt, flags, args...) \ -- alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args) -+ alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | \ -+ __WQ_ORDERED_EXPLICIT | (flags), 1, ##args) - - #define create_workqueue(name) \ - alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, (name)) -diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h -index e0f4109e64c6..c2aa73e5e6bb 100644 ---- a/include/net/iw_handler.h -+++ b/include/net/iw_handler.h -@@ -556,7 +556,8 @@ iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, - memcpy(stream + lcp_len, - ((char *) &iwe->u) + IW_EV_POINT_OFF, - IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); -- memcpy(stream + point_len, extra, iwe->u.data.length); -+ if (iwe->u.data.length && extra) -+ memcpy(stream + point_len, extra, iwe->u.data.length); - stream += event_len; - } - return stream; -diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h -index ce13cf20f625..d33b17ba51d2 100644 ---- a/include/net/sctp/sctp.h -+++ b/include/net/sctp/sctp.h -@@ -444,6 +444,8 @@ _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) - - #define _sctp_walk_params(pos, chunk, end, member)\ - for (pos.v = chunk->member;\ -+ (pos.v + offsetof(struct sctp_paramhdr, length) + sizeof(pos.p->length) <=\ -+ (void *)chunk + end) &&\ - pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ - ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ - pos.v += WORD_ROUND(ntohs(pos.p->length))) -@@ -454,6 +456,8 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) - #define _sctp_walk_errors(err, chunk_hdr, end)\ - for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ - sizeof(sctp_chunkhdr_t));\ -+ ((void *)err + offsetof(sctp_errhdr_t, length) + sizeof(err->length) <=\ -+ (void *)chunk_hdr + end) &&\ - (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ - ntohs(err->length) >= sizeof(sctp_errhdr_t); \ - err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) -diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h -index e0efe3fcf739..fdda45f26f75 100644 ---- a/include/target/iscsi/iscsi_target_core.h -+++ b/include/target/iscsi/iscsi_target_core.h -@@ -562,6 +562,7 @@ struct iscsi_conn { - #define LOGIN_FLAGS_READ_ACTIVE 1 - #define LOGIN_FLAGS_CLOSED 2 - #define LOGIN_FLAGS_READY 4 -+#define LOGIN_FLAGS_INITIAL_PDU 8 - unsigned long login_flags; - struct delayed_work login_work; - struct delayed_work login_cleanup_work; -diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h -index ed66414b91f0..1adf8739980c 100644 ---- a/include/target/target_core_base.h -+++ b/include/target/target_core_base.h -@@ -714,6 +714,7 @@ struct se_lun { - #define SE_LUN_LINK_MAGIC 0xffff7771 - u32 lun_link_magic; - u32 lun_access; -+ bool lun_shutdown; - u32 lun_index; - - /* RELATIVE TARGET PORT IDENTIFER */ -diff --git a/kernel/signal.c b/kernel/signal.c -index b92a047ddc82..5d50ea899b6d 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -346,7 +346,7 @@ static bool task_participate_group_stop(struct task_struct *task) - * fresh group stop. Read comment in do_signal_stop() for details. - */ - if (!sig->group_stop_count && !(sig->flags & SIGNAL_STOP_STOPPED)) { -- sig->flags = SIGNAL_STOP_STOPPED; -+ signal_set_stop_flags(sig, SIGNAL_STOP_STOPPED); - return true; - } - return false; -@@ -845,7 +845,7 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force) - * will take ->siglock, notice SIGNAL_CLD_MASK, and - * notify its parent. See get_signal_to_deliver(). - */ -- signal->flags = why | SIGNAL_STOP_CONTINUED; -+ signal_set_stop_flags(signal, why | SIGNAL_STOP_CONTINUED); - signal->group_stop_count = 0; - signal->group_exit_code = 0; - } -diff --git a/kernel/workqueue.c b/kernel/workqueue.c -index 2c2f971f3e75..23231237f2e2 100644 ---- a/kernel/workqueue.c -+++ b/kernel/workqueue.c -@@ -3647,8 +3647,12 @@ static int apply_workqueue_attrs_locked(struct workqueue_struct *wq, - return -EINVAL; - - /* creating multiple pwqs breaks ordering guarantee */ -- if (WARN_ON((wq->flags & __WQ_ORDERED) && !list_empty(&wq->pwqs))) -- return -EINVAL; -+ if (!list_empty(&wq->pwqs)) { -+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) -+ return -EINVAL; -+ -+ wq->flags &= ~__WQ_ORDERED; -+ } - - ctx = apply_wqattrs_prepare(wq, attrs); - -@@ -3834,6 +3838,16 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, - struct workqueue_struct *wq; - struct pool_workqueue *pwq; - -+ /* -+ * Unbound && max_active == 1 used to imply ordered, which is no -+ * longer the case on NUMA machines due to per-node pools. While -+ * alloc_ordered_workqueue() is the right way to create an ordered -+ * workqueue, keep the previous behavior to avoid subtle breakages -+ * on NUMA. -+ */ -+ if ((flags & WQ_UNBOUND) && max_active == 1) -+ flags |= __WQ_ORDERED; -+ - /* see the comment above the definition of WQ_POWER_EFFICIENT */ - if ((flags & WQ_POWER_EFFICIENT) && wq_power_efficient) - flags |= WQ_UNBOUND; -@@ -4022,13 +4036,14 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) - struct pool_workqueue *pwq; - - /* disallow meddling with max_active for ordered workqueues */ -- if (WARN_ON(wq->flags & __WQ_ORDERED)) -+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) - return; - - max_active = wq_clamp_max_active(max_active, wq->flags, wq->name); - - mutex_lock(&wq->mutex); - -+ wq->flags &= ~__WQ_ORDERED; - wq->saved_max_active = max_active; - - for_each_pwq(pwq, wq) -@@ -5154,7 +5169,7 @@ int workqueue_sysfs_register(struct workqueue_struct *wq) - * attributes breaks ordering guarantee. Disallow exposing ordered - * workqueues. - */ -- if (WARN_ON(wq->flags & __WQ_ORDERED)) -+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) - return -EINVAL; - - wq->wq_dev = wq_dev = kzalloc(sizeof(*wq_dev), GFP_KERNEL); -diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug -index 8c15b29d5adc..b53b375e14bd 100644 ---- a/lib/Kconfig.debug -+++ b/lib/Kconfig.debug -@@ -145,7 +145,7 @@ config DEBUG_INFO_REDUCED - - config DEBUG_INFO_SPLIT - bool "Produce split debuginfo in .dwo files" -- depends on DEBUG_INFO -+ depends on DEBUG_INFO && !FRV - help - Generate debug info into separate .dwo files. This significantly - reduces the build directory size for builds with DEBUG_INFO, -diff --git a/mm/internal.h b/mm/internal.h -index 6979b2bd3227..f63f4393d633 100644 ---- a/mm/internal.h -+++ b/mm/internal.h -@@ -453,6 +453,7 @@ struct tlbflush_unmap_batch; - #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH - void try_to_unmap_flush(void); - void try_to_unmap_flush_dirty(void); -+void flush_tlb_batched_pending(struct mm_struct *mm); - #else - static inline void try_to_unmap_flush(void) - { -@@ -460,6 +461,8 @@ static inline void try_to_unmap_flush(void) - static inline void try_to_unmap_flush_dirty(void) - { - } -- -+static inline void flush_tlb_batched_pending(struct mm_struct *mm) -+{ -+} - #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */ - #endif /* __MM_INTERNAL_H */ -diff --git a/mm/memory.c b/mm/memory.c -index e6fa13484447..9ac55172aa7b 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1127,6 +1127,7 @@ again: - init_rss_vec(rss); - start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - pte = start_pte; -+ flush_tlb_batched_pending(mm); - arch_enter_lazy_mmu_mode(); - do { - pte_t ptent = *pte; -diff --git a/mm/mprotect.c b/mm/mprotect.c -index ef5be8eaab00..c0b4b2a49462 100644 ---- a/mm/mprotect.c -+++ b/mm/mprotect.c -@@ -72,6 +72,7 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, - if (!pte) - return 0; - -+ flush_tlb_batched_pending(vma->vm_mm); - arch_enter_lazy_mmu_mode(); - do { - oldpte = *pte; -diff --git a/mm/mremap.c b/mm/mremap.c -index c25bc6268e46..fe7b7f65f4f4 100644 ---- a/mm/mremap.c -+++ b/mm/mremap.c -@@ -135,6 +135,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, - new_ptl = pte_lockptr(mm, new_pmd); - if (new_ptl != old_ptl) - spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); -+ flush_tlb_batched_pending(vma->vm_mm); - arch_enter_lazy_mmu_mode(); - - for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE, -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index bd17a6bdf131..f9d648fce8cd 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -1527,14 +1527,14 @@ int move_freepages(struct zone *zone, - #endif - - for (page = start_page; page <= end_page;) { -- /* Make sure we are not inadvertently changing nodes */ -- VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page); -- - if (!pfn_valid_within(page_to_pfn(page))) { - page++; - continue; - } - -+ /* Make sure we are not inadvertently changing nodes */ -+ VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page); -+ - if (!PageBuddy(page)) { - page++; - continue; -@@ -5847,8 +5847,8 @@ unsigned long free_reserved_area(void *start, void *end, int poison, char *s) - } - - if (pages && s) -- pr_info("Freeing %s memory: %ldK (%p - %p)\n", -- s, pages << (PAGE_SHIFT - 10), start, end); -+ pr_info("Freeing %s memory: %ldK\n", -+ s, pages << (PAGE_SHIFT - 10)); - - return pages; - } -diff --git a/mm/rmap.c b/mm/rmap.c -index b577fbb98d4b..ede183c32f45 100644 ---- a/mm/rmap.c -+++ b/mm/rmap.c -@@ -648,6 +648,13 @@ static void set_tlb_ubc_flush_pending(struct mm_struct *mm, - cpumask_or(&tlb_ubc->cpumask, &tlb_ubc->cpumask, mm_cpumask(mm)); - tlb_ubc->flush_required = true; - -+ /* -+ * Ensure compiler does not re-order the setting of tlb_flush_batched -+ * before the PTE is cleared. -+ */ -+ barrier(); -+ mm->tlb_flush_batched = true; -+ - /* - * If the PTE was dirty then it's best to assume it's writable. The - * caller must use try_to_unmap_flush_dirty() or try_to_unmap_flush() -@@ -675,6 +682,35 @@ static bool should_defer_flush(struct mm_struct *mm, enum ttu_flags flags) - - return should_defer; - } -+ -+/* -+ * Reclaim unmaps pages under the PTL but do not flush the TLB prior to -+ * releasing the PTL if TLB flushes are batched. It's possible for a parallel -+ * operation such as mprotect or munmap to race between reclaim unmapping -+ * the page and flushing the page. If this race occurs, it potentially allows -+ * access to data via a stale TLB entry. Tracking all mm's that have TLB -+ * batching in flight would be expensive during reclaim so instead track -+ * whether TLB batching occurred in the past and if so then do a flush here -+ * if required. This will cost one additional flush per reclaim cycle paid -+ * by the first operation at risk such as mprotect and mumap. -+ * -+ * This must be called under the PTL so that an access to tlb_flush_batched -+ * that is potentially a "reclaim vs mprotect/munmap/etc" race will synchronise -+ * via the PTL. -+ */ -+void flush_tlb_batched_pending(struct mm_struct *mm) -+{ -+ if (mm->tlb_flush_batched) { -+ flush_tlb_mm(mm); -+ -+ /* -+ * Do not allow the compiler to re-order the clearing of -+ * tlb_flush_batched before the tlb is flushed. -+ */ -+ barrier(); -+ mm->tlb_flush_batched = false; -+ } -+} - #else - static void set_tlb_ubc_flush_pending(struct mm_struct *mm, - struct page *page, bool writable) -diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c -index b94b1d293506..151e047ce072 100644 ---- a/net/core/dev_ioctl.c -+++ b/net/core/dev_ioctl.c -@@ -28,6 +28,7 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg) - - if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) - return -EFAULT; -+ ifr.ifr_name[IFNAMSIZ-1] = 0; - - error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex); - if (error) -diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index 2ec5324a7ff7..5b3d611d8b5f 100644 ---- a/net/core/rtnetlink.c -+++ b/net/core/rtnetlink.c -@@ -1742,7 +1742,8 @@ static int do_setlink(const struct sk_buff *skb, - struct sockaddr *sa; - int len; - -- len = sizeof(sa_family_t) + dev->addr_len; -+ len = sizeof(sa_family_t) + max_t(size_t, dev->addr_len, -+ sizeof(*sa)); - sa = kmalloc(len, GFP_KERNEL); - if (!sa) { - err = -ENOMEM; -diff --git a/net/dccp/feat.c b/net/dccp/feat.c -index 1704948e6a12..f227f002c73d 100644 ---- a/net/dccp/feat.c -+++ b/net/dccp/feat.c -@@ -1471,9 +1471,12 @@ int dccp_feat_init(struct sock *sk) - * singleton values (which always leads to failure). - * These settings can still (later) be overridden via sockopts. - */ -- if (ccid_get_builtin_ccids(&tx.val, &tx.len) || -- ccid_get_builtin_ccids(&rx.val, &rx.len)) -+ if (ccid_get_builtin_ccids(&tx.val, &tx.len)) - return -ENOBUFS; -+ if (ccid_get_builtin_ccids(&rx.val, &rx.len)) { -+ kfree(tx.val); -+ return -ENOBUFS; -+ } - - if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) || - !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len)) -diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c -index 6467bf392e1b..e217f17997a4 100644 ---- a/net/dccp/ipv4.c -+++ b/net/dccp/ipv4.c -@@ -635,6 +635,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) - goto drop_and_free; - - inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); -+ reqsk_put(req); - return 0; - - drop_and_free: -diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c -index 3470ad1843bb..09a9ab65f4e1 100644 ---- a/net/dccp/ipv6.c -+++ b/net/dccp/ipv6.c -@@ -376,6 +376,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) - goto drop_and_free; - - inet_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT); -+ reqsk_put(req); - return 0; - - drop_and_free: -diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c -index 66dcb529fd9c..0cb240c749bf 100644 ---- a/net/ipv4/fib_frontend.c -+++ b/net/ipv4/fib_frontend.c -@@ -1319,13 +1319,14 @@ static struct pernet_operations fib_net_ops = { - - void __init ip_fib_init(void) - { -- rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); -- rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); -- rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); -+ fib_trie_init(); - - register_pernet_subsys(&fib_net_ops); -+ - register_netdevice_notifier(&fib_netdev_notifier); - register_inetaddr_notifier(&fib_inetaddr_notifier); - -- fib_trie_init(); -+ rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, NULL); -+ rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, NULL); -+ rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, NULL); - } -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c -index 2b7283303650..5d58a6703a43 100644 ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c -@@ -922,7 +922,8 @@ static int __ip_append_data(struct sock *sk, - csummode = CHECKSUM_PARTIAL; - - cork->length += length; -- if (((length > mtu) || (skb && skb_is_gso(skb))) && -+ if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) || -+ (skb && skb_is_gso(skb))) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && - (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) { -diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c -index 4cbe9f0a4281..731b91409625 100644 ---- a/net/ipv4/syncookies.c -+++ b/net/ipv4/syncookies.c -@@ -337,6 +337,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) - treq = tcp_rsk(req); - treq->rcv_isn = ntohl(th->seq) - 1; - treq->snt_isn = cookie; -+ treq->txhash = net_tx_rndhash(); - req->mss = mss; - ireq->ir_num = ntohs(th->dest); - ireq->ir_rmt_port = th->source; -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 150b4923fb72..0de3245ea42f 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -647,8 +647,6 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, - *prevhdr = NEXTHDR_FRAGMENT; - tmp_hdr = kmemdup(skb_network_header(skb), hlen, GFP_ATOMIC); - if (!tmp_hdr) { -- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), -- IPSTATS_MIB_FRAGFAILS); - err = -ENOMEM; - goto fail; - } -@@ -767,8 +765,6 @@ slow_path: - frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) + - hroom + troom, GFP_ATOMIC); - if (!frag) { -- IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), -- IPSTATS_MIB_FRAGFAILS); - err = -ENOMEM; - goto fail; - } -@@ -1361,7 +1357,7 @@ emsgsize: - */ - - cork->length += length; -- if ((((length + fragheaderlen) > mtu) || -+ if ((((length + (skb ? skb->len : headersize)) > mtu) || - (skb && skb_is_gso(skb))) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && -diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c -index 8b56c5240429..f9f02581c4ca 100644 ---- a/net/ipv6/output_core.c -+++ b/net/ipv6/output_core.c -@@ -78,7 +78,7 @@ EXPORT_SYMBOL(ipv6_select_ident); - - int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - { -- u16 offset = sizeof(struct ipv6hdr); -+ unsigned int offset = sizeof(struct ipv6hdr); - unsigned int packet_len = skb_tail_pointer(skb) - - skb_network_header(skb); - int found_rhdr = 0; -@@ -86,6 +86,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - - while (offset <= packet_len) { - struct ipv6_opt_hdr *exthdr; -+ unsigned int len; - - switch (**nexthdr) { - -@@ -111,7 +112,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - - exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + - offset); -- offset += ipv6_optlen(exthdr); -+ len = ipv6_optlen(exthdr); -+ if (len + offset >= IPV6_MAXPLEN) -+ return -EINVAL; -+ offset += len; - *nexthdr = &exthdr->nexthdr; - } - -diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c -index eaf7ac496d50..aee87282d352 100644 ---- a/net/ipv6/syncookies.c -+++ b/net/ipv6/syncookies.c -@@ -210,6 +210,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) - treq->snt_synack.v64 = 0; - treq->rcv_isn = ntohl(th->seq) - 1; - treq->snt_isn = cookie; -+ treq->txhash = net_tx_rndhash(); - - /* - * We need to lookup the dst_entry to get the correct window size. -diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c -index ad58d2a6284e..6a2507f24b0f 100644 ---- a/net/openvswitch/conntrack.c -+++ b/net/openvswitch/conntrack.c -@@ -577,8 +577,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, - - nla_for_each_nested(a, attr, rem) { - int type = nla_type(a); -- int maxlen = ovs_ct_attr_lens[type].maxlen; -- int minlen = ovs_ct_attr_lens[type].minlen; -+ int maxlen; -+ int minlen; - - if (type > OVS_CT_ATTR_MAX) { - OVS_NLERR(log, -@@ -586,6 +586,9 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, - type, OVS_CT_ATTR_MAX); - return -EINVAL; - } -+ -+ maxlen = ovs_ct_attr_lens[type].maxlen; -+ minlen = ovs_ct_attr_lens[type].minlen; - if (nla_len(a) < minlen || nla_len(a) > maxlen) { - OVS_NLERR(log, - "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)", -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index f8d6a0ca9c03..061771ca2582 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -4225,7 +4225,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, - register_prot_hook(sk); - } - spin_unlock(&po->bind_lock); -- if (closing && (po->tp_version > TPACKET_V2)) { -+ if (pg_vec && (po->tp_version > TPACKET_V2)) { - /* Because we don't support block-based V3 on tx-ring */ - if (!tx_ring) - prb_shutdown_retire_blk_timer(po, rb_queue); -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 46a34039ecdc..5cab24f52825 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -2233,6 +2233,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3), - SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), - SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), -+ SND_PCI_QUIRK(0x104d, 0x9060, "Sony Vaio VPCL14M1R", ALC882_FIXUP_NO_PRIMARY_HP), - SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP), - SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP), - -diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c -index a1e605bbc465..977066ba1769 100644 ---- a/sound/soc/soc-pcm.c -+++ b/sound/soc/soc-pcm.c -@@ -181,6 +181,10 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, - dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n", - be->dai_link->name, event, dir); - -+ if ((event == SND_SOC_DAPM_STREAM_STOP) && -+ (be->dpcm[dir].users >= 1)) -+ continue; -+ - snd_soc_dapm_stream_event(be, dir, event); - } - diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.81-82.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.81-82.patch deleted file mode 100644 index f61b7675a..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.81-82.patch +++ /dev/null @@ -1,330 +0,0 @@ -diff --git a/Makefile b/Makefile -index d049e53a6960..52f2dd8dcebd 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 81 -+SUBLEVEL = 82 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c -index 1f1ff7e7b9cf..ba079e279b58 100644 ---- a/arch/arm/kvm/mmu.c -+++ b/arch/arm/kvm/mmu.c -@@ -1629,12 +1629,16 @@ static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data) - - int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end) - { -+ if (!kvm->arch.pgd) -+ return 0; - trace_kvm_age_hva(start, end); - return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL); - } - - int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) - { -+ if (!kvm->arch.pgd) -+ return 0; - trace_kvm_test_age_hva(hva); - return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL); - } -diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c -index 0e2919dd8df3..1395eeb6005f 100644 ---- a/arch/s390/net/bpf_jit_comp.c -+++ b/arch/s390/net/bpf_jit_comp.c -@@ -1250,7 +1250,8 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp) - insn_count = bpf_jit_insn(jit, fp, i); - if (insn_count < 0) - return -1; -- jit->addrs[i + 1] = jit->prg; /* Next instruction address */ -+ /* Next instruction address */ -+ jit->addrs[i + insn_count] = jit->prg; - } - bpf_jit_epilogue(jit); - -diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h -index 349dd23e2876..0cdeb2b483a0 100644 ---- a/arch/sparc/include/asm/mmu_context_64.h -+++ b/arch/sparc/include/asm/mmu_context_64.h -@@ -25,9 +25,11 @@ void destroy_context(struct mm_struct *mm); - void __tsb_context_switch(unsigned long pgd_pa, - struct tsb_config *tsb_base, - struct tsb_config *tsb_huge, -- unsigned long tsb_descr_pa); -+ unsigned long tsb_descr_pa, -+ unsigned long secondary_ctx); - --static inline void tsb_context_switch(struct mm_struct *mm) -+static inline void tsb_context_switch_ctx(struct mm_struct *mm, -+ unsigned long ctx) - { - __tsb_context_switch(__pa(mm->pgd), - &mm->context.tsb_block[0], -@@ -38,9 +40,12 @@ static inline void tsb_context_switch(struct mm_struct *mm) - #else - NULL - #endif -- , __pa(&mm->context.tsb_descr[0])); -+ , __pa(&mm->context.tsb_descr[0]), -+ ctx); - } - -+#define tsb_context_switch(X) tsb_context_switch_ctx(X, 0) -+ - void tsb_grow(struct mm_struct *mm, - unsigned long tsb_index, - unsigned long mm_rss); -@@ -110,8 +115,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str - * cpu0 to update it's TSB because at that point the cpu_vm_mask - * only had cpu1 set in it. - */ -- load_secondary_context(mm); -- tsb_context_switch(mm); -+ tsb_context_switch_ctx(mm, CTX_HWBITS(mm->context)); - - /* Any time a processor runs a context on an address space - * for the first time, we must flush that context out of the -diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S -index 395ec1800530..7d961f6e3907 100644 ---- a/arch/sparc/kernel/tsb.S -+++ b/arch/sparc/kernel/tsb.S -@@ -375,6 +375,7 @@ tsb_flush: - * %o1: TSB base config pointer - * %o2: TSB huge config pointer, or NULL if none - * %o3: Hypervisor TSB descriptor physical address -+ * %o4: Secondary context to load, if non-zero - * - * We have to run this whole thing with interrupts - * disabled so that the current cpu doesn't change -@@ -387,6 +388,17 @@ __tsb_context_switch: - rdpr %pstate, %g1 - wrpr %g1, PSTATE_IE, %pstate - -+ brz,pn %o4, 1f -+ mov SECONDARY_CONTEXT, %o5 -+ -+661: stxa %o4, [%o5] ASI_DMMU -+ .section .sun4v_1insn_patch, "ax" -+ .word 661b -+ stxa %o4, [%o5] ASI_MMU -+ .previous -+ flush %g6 -+ -+1: - TRAP_LOAD_TRAP_BLOCK(%g2, %g3) - - stx %o0, [%g2 + TRAP_PER_CPU_PGD_PADDR] -diff --git a/arch/sparc/power/hibernate.c b/arch/sparc/power/hibernate.c -index 17bd2e167e07..df707a8ad311 100644 ---- a/arch/sparc/power/hibernate.c -+++ b/arch/sparc/power/hibernate.c -@@ -35,6 +35,5 @@ void restore_processor_state(void) - { - struct mm_struct *mm = current->active_mm; - -- load_secondary_context(mm); -- tsb_context_switch(mm); -+ tsb_context_switch_ctx(mm, CTX_HWBITS(mm->context)); - } -diff --git a/mm/mempool.c b/mm/mempool.c -index 004d42b1dfaf..7924f4f58a6d 100644 ---- a/mm/mempool.c -+++ b/mm/mempool.c -@@ -135,8 +135,8 @@ static void *remove_element(mempool_t *pool) - void *element = pool->elements[--pool->curr_nr]; - - BUG_ON(pool->curr_nr < 0); -- check_element(pool, element); - kasan_unpoison_element(pool, element); -+ check_element(pool, element); - return element; - } - -diff --git a/net/core/dev.c b/net/core/dev.c -index 4b0853194a03..24d243084aab 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2551,7 +2551,7 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) - { - if (tx_path) - return skb->ip_summed != CHECKSUM_PARTIAL && -- skb->ip_summed != CHECKSUM_NONE; -+ skb->ip_summed != CHECKSUM_UNNECESSARY; - - return skb->ip_summed == CHECKSUM_NONE; - } -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c -index 5d58a6703a43..09c73dd541c5 100644 ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c -@@ -922,11 +922,12 @@ static int __ip_append_data(struct sock *sk, - csummode = CHECKSUM_PARTIAL; - - cork->length += length; -- if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) || -- (skb && skb_is_gso(skb))) && -+ if ((skb && skb_is_gso(skb)) || -+ (((length + (skb ? skb->len : fragheaderlen)) > mtu) && -+ (skb_queue_len(queue) <= 1) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && -- (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) { -+ (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx)) { - err = ip_ufo_append_data(sk, queue, getfrag, from, length, - hh_len, fragheaderlen, transhdrlen, - maxfraglen, flags); -@@ -1242,6 +1243,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, - return -EINVAL; - - if ((size + skb->len > mtu) && -+ (skb_queue_len(&sk->sk_write_queue) == 1) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO)) { - if (skb->ip_summed != CHECKSUM_PARTIAL) -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 8f13b2eaabf8..f0dabd125c43 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -2503,8 +2503,8 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk) - struct tcp_sock *tp = tcp_sk(sk); - - /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */ -- if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || -- (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) { -+ if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH && -+ (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || tp->undo_marker)) { - tp->snd_cwnd = tp->snd_ssthresh; - tp->snd_cwnd_stamp = tcp_time_stamp; - } -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 3fdcdc730f71..850d1b5bfd81 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -3256,6 +3256,9 @@ int tcp_connect(struct sock *sk) - struct sk_buff *buff; - int err; - -+ if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) -+ return -EHOSTUNREACH; /* Routing failure or similar. */ -+ - tcp_connect_init(sk); - - if (unlikely(tp->repair)) { -diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c -index ebb34d0c5e80..1ec12a4f327e 100644 ---- a/net/ipv4/tcp_timer.c -+++ b/net/ipv4/tcp_timer.c -@@ -606,7 +606,8 @@ static void tcp_keepalive_timer (unsigned long data) - goto death; - } - -- if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) -+ if (!sock_flag(sk, SOCK_KEEPOPEN) || -+ ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT))) - goto out; - - elapsed = keepalive_time_when(tp); -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index e9513e397c4f..301e60829c7e 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -819,7 +819,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) - if (is_udplite) /* UDP-Lite */ - csum = udplite_csum(skb); - -- else if (sk->sk_no_check_tx) { /* UDP csum disabled */ -+ else if (sk->sk_no_check_tx && !skb_is_gso(skb)) { /* UDP csum off */ - - skb->ip_summed = CHECKSUM_NONE; - goto send; -diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c -index 6396f1c80ae9..6dfc3daf7c21 100644 ---- a/net/ipv4/udp_offload.c -+++ b/net/ipv4/udp_offload.c -@@ -231,7 +231,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; - -- skb->ip_summed = CHECKSUM_NONE; -+ skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Fragment the skb. IP headers of the fragments are updated in - * inet_gso_segment() -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 0de3245ea42f..e22339fad10b 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1357,11 +1357,12 @@ emsgsize: - */ - - cork->length += length; -- if ((((length + (skb ? skb->len : headersize)) > mtu) || -- (skb && skb_is_gso(skb))) && -+ if ((skb && skb_is_gso(skb)) || -+ (((length + (skb ? skb->len : headersize)) > mtu) && -+ (skb_queue_len(queue) <= 1) && - (sk->sk_protocol == IPPROTO_UDP) && - (rt->dst.dev->features & NETIF_F_UFO) && -- (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) { -+ (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk))) { - err = ip6_ufo_append_data(sk, queue, getfrag, from, length, - hh_len, fragheaderlen, exthdrlen, - transhdrlen, mtu, flags, fl6); -diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c -index 01582966ffa0..2e3c12eeca07 100644 ---- a/net/ipv6/udp_offload.c -+++ b/net/ipv6/udp_offload.c -@@ -86,7 +86,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; - -- skb->ip_summed = CHECKSUM_NONE; -+ skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Check if there is enough headroom to insert fragment header. */ - tnl_hlen = skb_tnl_header_len(skb); -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 061771ca2582..148ec130d99d 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -3622,14 +3622,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv - - if (optlen != sizeof(val)) - return -EINVAL; -- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) -- return -EBUSY; - if (copy_from_user(&val, optval, sizeof(val))) - return -EFAULT; - if (val > INT_MAX) - return -EINVAL; -- po->tp_reserve = val; -- return 0; -+ lock_sock(sk); -+ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { -+ ret = -EBUSY; -+ } else { -+ po->tp_reserve = val; -+ ret = 0; -+ } -+ release_sock(sk); -+ return ret; - } - case PACKET_LOSS: - { -diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c -index d05869646515..0915d448ba23 100644 ---- a/net/sched/act_ipt.c -+++ b/net/sched/act_ipt.c -@@ -42,8 +42,8 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int - return PTR_ERR(target); - - t->u.kernel.target = target; -+ memset(&par, 0, sizeof(par)); - par.table = table; -- par.entryinfo = NULL; - par.target = target; - par.targinfo = t->data; - par.hook_mask = hook; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.82-83.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.82-83.patch deleted file mode 100644 index 104c0c331..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.82-83.patch +++ /dev/null @@ -1,476 +0,0 @@ -diff --git a/Makefile b/Makefile -index 52f2dd8dcebd..7f67b35caf99 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 82 -+SUBLEVEL = 83 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c -index fa24d5196615..c7122919a8c0 100644 ---- a/drivers/iio/accel/bmc150-accel-core.c -+++ b/drivers/iio/accel/bmc150-accel-core.c -@@ -194,7 +194,6 @@ struct bmc150_accel_data { - struct device *dev; - int irq; - struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS]; -- atomic_t active_intr; - struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS]; - struct mutex mutex; - u8 fifo_mode, watermark; -@@ -489,11 +488,6 @@ static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i, - goto out_fix_power_state; - } - -- if (state) -- atomic_inc(&data->active_intr); -- else -- atomic_dec(&data->active_intr); -- - return 0; - - out_fix_power_state: -@@ -1704,8 +1698,7 @@ static int bmc150_accel_resume(struct device *dev) - struct bmc150_accel_data *data = iio_priv(indio_dev); - - mutex_lock(&data->mutex); -- if (atomic_read(&data->active_intr)) -- bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); -+ bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0); - bmc150_accel_fifo_set_mode(data); - mutex_unlock(&data->mutex); - -diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c -index b10f629cc44b..1dbc2143cdfc 100644 ---- a/drivers/iio/adc/vf610_adc.c -+++ b/drivers/iio/adc/vf610_adc.c -@@ -77,7 +77,7 @@ - #define VF610_ADC_ADSTS_MASK 0x300 - #define VF610_ADC_ADLPC_EN 0x80 - #define VF610_ADC_ADHSC_EN 0x400 --#define VF610_ADC_REFSEL_VALT 0x100 -+#define VF610_ADC_REFSEL_VALT 0x800 - #define VF610_ADC_REFSEL_VBG 0x1000 - #define VF610_ADC_ADTRG_HARD 0x2000 - #define VF610_ADC_AVGS_8 0x4000 -diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c -index 12731d6b89ec..ec1b2e798cc1 100644 ---- a/drivers/iio/light/tsl2563.c -+++ b/drivers/iio/light/tsl2563.c -@@ -626,7 +626,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private) - struct tsl2563_chip *chip = iio_priv(dev_info); - - iio_push_event(dev_info, -- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, -+ IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, - 0, - IIO_EV_TYPE_THRESH, - IIO_EV_DIR_EITHER), -diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c -index 71ccf6a90b22..2551e4adb33f 100644 ---- a/drivers/pinctrl/samsung/pinctrl-exynos.c -+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c -@@ -194,8 +194,6 @@ static int exynos_irq_request_resources(struct irq_data *irqd) - - spin_unlock_irqrestore(&bank->slock, flags); - -- exynos_irq_unmask(irqd); -- - return 0; - } - -@@ -216,8 +214,6 @@ static void exynos_irq_release_resources(struct irq_data *irqd) - shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC]; - mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; - -- exynos_irq_mask(irqd); -- - spin_lock_irqsave(&bank->slock, flags); - - con = readl(d->virt_base + reg_con); -diff --git a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c -index 862a096c5dba..be5c71df148d 100644 ---- a/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c -@@ -811,6 +811,7 @@ static const struct sunxi_desc_pin sun4i_a10_pins[] = { - SUNXI_FUNCTION(0x2, "lcd1"), /* D16 */ - SUNXI_FUNCTION(0x3, "pata"), /* ATAD12 */ - SUNXI_FUNCTION(0x4, "keypad"), /* IN6 */ -+ SUNXI_FUNCTION(0x5, "sim"), /* DET */ - SUNXI_FUNCTION_IRQ(0x6, 16), /* EINT16 */ - SUNXI_FUNCTION(0x7, "csi1")), /* D16 */ - SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 17), -diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c -index d97aa2827412..8eb7179da342 100644 ---- a/drivers/staging/iio/resolver/ad2s1210.c -+++ b/drivers/staging/iio/resolver/ad2s1210.c -@@ -468,7 +468,7 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev, - long m) - { - struct ad2s1210_state *st = iio_priv(indio_dev); -- bool negative; -+ u16 negative; - int ret = 0; - u16 pos; - s16 vel; -diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c -index 31d5d9c0e10b..1ff1c83e2df5 100644 ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -418,6 +418,7 @@ int iscsit_reset_np_thread( - return 0; - } - np->np_thread_state = ISCSI_NP_THREAD_RESET; -+ atomic_inc(&np->np_reset_count); - - if (np->np_thread) { - spin_unlock_bh(&np->np_thread_lock); -@@ -1996,6 +1997,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, - cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); - cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); - cmd->data_direction = DMA_NONE; -+ kfree(cmd->text_in_ptr); - cmd->text_in_ptr = NULL; - - return 0; -diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c -index b19edffa7d98..bc2cbffec27e 100644 ---- a/drivers/target/iscsi/iscsi_target_login.c -+++ b/drivers/target/iscsi/iscsi_target_login.c -@@ -1219,9 +1219,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) - flush_signals(current); - - spin_lock_bh(&np->np_thread_lock); -- if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { -+ if (atomic_dec_if_positive(&np->np_reset_count) >= 0) { - np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; -+ spin_unlock_bh(&np->np_thread_lock); - complete(&np->np_restart_comp); -+ return 1; - } else if (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN) { - spin_unlock_bh(&np->np_thread_lock); - goto exit; -@@ -1254,7 +1256,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) - goto exit; - } else if (rc < 0) { - spin_lock_bh(&np->np_thread_lock); -- if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { -+ if (atomic_dec_if_positive(&np->np_reset_count) >= 0) { -+ np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; - spin_unlock_bh(&np->np_thread_lock); - complete(&np->np_restart_comp); - iscsit_put_transport(conn->conn_transport); -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index b403596818db..5c0952995280 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -1851,7 +1851,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, - /* No more submits can occur */ - spin_lock_irq(&hcd_urb_list_lock); - rescan: -- list_for_each_entry (urb, &ep->urb_list, urb_list) { -+ list_for_each_entry_reverse(urb, &ep->urb_list, urb_list) { - int is_in; - - if (urb->unlinked) -@@ -2448,6 +2448,8 @@ void usb_hc_died (struct usb_hcd *hcd) - } - if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) { - hcd = hcd->shared_hcd; -+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); -+ set_bit(HCD_FLAG_DEAD, &hcd->flags); - if (hcd->rh_registered) { - clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 1d59d489a1ad..cdf4be3939f5 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4661,7 +4661,8 @@ hub_power_remaining(struct usb_hub *hub) - static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - u16 portchange) - { -- int status, i; -+ int status = -ENODEV; -+ int i; - unsigned unit_load; - struct usb_device *hdev = hub->hdev; - struct usb_hcd *hcd = bus_to_hcd(hdev->bus); -@@ -4865,9 +4866,10 @@ loop: - - done: - hub_port_disable(hub, port1, 1); -- if (hcd->driver->relinquish_port && !hub->hdev->parent) -- hcd->driver->relinquish_port(hcd, port1); -- -+ if (hcd->driver->relinquish_port && !hub->hdev->parent) { -+ if (status != -ENOTCONN && status != -ENODEV) -+ hcd->driver->relinquish_port(hcd, port1); -+ } - } - - /* Handle physical or logical connection change events. -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 3116edfcdc18..574da2b4529c 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -150,6 +150,9 @@ static const struct usb_device_id usb_quirk_list[] = { - /* appletouch */ - { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, - -+ /* Genesys Logic hub, internally used by Moshi USB to Ethernet Adapter */ -+ { USB_DEVICE(0x05e3, 0x0616), .driver_info = USB_QUIRK_NO_LPM }, -+ - /* Avision AV600U */ - { USB_DEVICE(0x0638, 0x0a13), .driver_info = - USB_QUIRK_STRING_FETCH_255 }, -@@ -249,6 +252,7 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { - { USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME }, - { USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME }, - { USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME }, -+ { USB_DEVICE(0x03f0, 0x2b4a), .driver_info = USB_QUIRK_RESET_RESUME }, - - /* Logitech Optical Mouse M90/M100 */ - { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, -diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c -index f9400564cb72..03b9a372636f 100644 ---- a/drivers/usb/host/pci-quirks.c -+++ b/drivers/usb/host/pci-quirks.c -@@ -89,6 +89,7 @@ enum amd_chipset_gen { - AMD_CHIPSET_HUDSON2, - AMD_CHIPSET_BOLTON, - AMD_CHIPSET_YANGTZE, -+ AMD_CHIPSET_TAISHAN, - AMD_CHIPSET_UNKNOWN, - }; - -@@ -132,6 +133,11 @@ static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo) - pinfo->sb_type.gen = AMD_CHIPSET_SB700; - else if (rev >= 0x40 && rev <= 0x4f) - pinfo->sb_type.gen = AMD_CHIPSET_SB800; -+ } -+ pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, -+ 0x145c, NULL); -+ if (pinfo->smbus_dev) { -+ pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN; - } else { - pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL); -@@ -251,11 +257,12 @@ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev) - { - /* Make sure amd chipset type has already been initialized */ - usb_amd_find_chipset_info(); -- if (amd_chipset.sb_type.gen != AMD_CHIPSET_YANGTZE) -- return 0; -- -- dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n"); -- return 1; -+ if (amd_chipset.sb_type.gen == AMD_CHIPSET_YANGTZE || -+ amd_chipset.sb_type.gen == AMD_CHIPSET_TAISHAN) { -+ dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n"); -+ return 1; -+ } -+ return 0; - } - EXPORT_SYMBOL_GPL(usb_hcd_amd_remote_wakeup_quirk); - -diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c -index 13d5614f37f1..0d843e0f8055 100644 ---- a/drivers/usb/musb/musb_host.c -+++ b/drivers/usb/musb/musb_host.c -@@ -138,6 +138,7 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) - "Could not flush host TX%d fifo: csr: %04x\n", - ep->epnum, csr)) - return; -+ mdelay(1); - } - } - -diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c -index b0dc6da3d970..41a6513646de 100644 ---- a/drivers/usb/serial/cp210x.c -+++ b/drivers/usb/serial/cp210x.c -@@ -135,6 +135,7 @@ static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ - { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ - { USB_DEVICE(0x10C4, 0x8A5E) }, /* CEL EM3588 ZigBee USB Stick Long Range */ -+ { USB_DEVICE(0x10C4, 0x8B34) }, /* Qivicon ZigBee USB Radio Stick */ - { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index ebe51f11105d..fe123153b1a5 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -2025,6 +2025,8 @@ static const struct usb_device_id option_ids[] = { - { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) }, /* D-Link DWM-158 */ - { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ - .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, -+ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */ -+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */ -diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c -index 1db4b61bdf7b..a51b28379850 100644 ---- a/drivers/usb/serial/pl2303.c -+++ b/drivers/usb/serial/pl2303.c -@@ -49,6 +49,7 @@ static const struct usb_device_id id_table[] = { - { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, - { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, - { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, -+ { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_UC485) }, - { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) }, - { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, - { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, -diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h -index 09d9be88209e..3b5a15d1dc0d 100644 ---- a/drivers/usb/serial/pl2303.h -+++ b/drivers/usb/serial/pl2303.h -@@ -27,6 +27,7 @@ - #define ATEN_VENDOR_ID 0x0557 - #define ATEN_VENDOR_ID2 0x0547 - #define ATEN_PRODUCT_ID 0x2008 -+#define ATEN_PRODUCT_UC485 0x2021 - #define ATEN_PRODUCT_ID2 0x2118 - - #define IODATA_VENDOR_ID 0x04bb -diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h -index 53341a77d89f..a37ed1e59e99 100644 ---- a/drivers/usb/storage/unusual_uas.h -+++ b/drivers/usb/storage/unusual_uas.h -@@ -123,9 +123,9 @@ UNUSUAL_DEV(0x0bc2, 0xab2a, 0x0000, 0x9999, - /* Reported-by: Benjamin Tissoires */ - UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999, - "Initio Corporation", -- "", -+ "INIC-3069", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, -- US_FL_NO_ATA_1X), -+ US_FL_NO_ATA_1X | US_FL_IGNORE_RESIDUE), - - /* Reported-by: Tom Arild Naess */ - UNUSUAL_DEV(0x152d, 0x0539, 0x0000, 0x9999, -diff --git a/fs/fuse/file.c b/fs/fuse/file.c -index 11538a8be9f0..1a063cbfe503 100644 ---- a/fs/fuse/file.c -+++ b/fs/fuse/file.c -@@ -46,7 +46,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) - { - struct fuse_file *ff; - -- ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); -+ ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL); - if (unlikely(!ff)) - return NULL; - -diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig -index f31fd0dd92c6..b1daeafbea92 100644 ---- a/fs/nfs/Kconfig -+++ b/fs/nfs/Kconfig -@@ -121,6 +121,7 @@ config PNFS_FILE_LAYOUT - config PNFS_BLOCK - tristate - depends on NFS_V4_1 && BLK_DEV_DM -+ depends on 64BIT || LBDAF - default NFS_V4 - - config PNFS_OBJLAYOUT -diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -index e125e55de86d..2603d7589946 100644 ---- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c -+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -@@ -30,6 +30,7 @@ void nfs4_ff_layout_free_deviceid(struct nfs4_ff_layout_ds *mirror_ds) - { - nfs4_print_deviceid(&mirror_ds->id_node.deviceid); - nfs4_pnfs_ds_put(mirror_ds->ds); -+ kfree(mirror_ds->ds_versions); - kfree_rcu(mirror_ds, id_node.rcu); - } - -diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h -index 85a868ccb493..8397dc235e84 100644 ---- a/include/linux/cpuset.h -+++ b/include/linux/cpuset.h -@@ -16,6 +16,7 @@ - - #ifdef CONFIG_CPUSETS - -+extern struct static_key cpusets_pre_enable_key; - extern struct static_key cpusets_enabled_key; - static inline bool cpusets_enabled(void) - { -@@ -30,12 +31,14 @@ static inline int nr_cpusets(void) - - static inline void cpuset_inc(void) - { -+ static_key_slow_inc(&cpusets_pre_enable_key); - static_key_slow_inc(&cpusets_enabled_key); - } - - static inline void cpuset_dec(void) - { - static_key_slow_dec(&cpusets_enabled_key); -+ static_key_slow_dec(&cpusets_pre_enable_key); - } - - extern int cpuset_init(void); -@@ -104,7 +107,7 @@ extern void cpuset_print_current_mems_allowed(void); - */ - static inline unsigned int read_mems_allowed_begin(void) - { -- if (!cpusets_enabled()) -+ if (!static_key_false(&cpusets_pre_enable_key)) - return 0; - - return read_seqcount_begin(¤t->mems_allowed_seq); -@@ -118,7 +121,7 @@ static inline unsigned int read_mems_allowed_begin(void) - */ - static inline bool read_mems_allowed_retry(unsigned int seq) - { -- if (!cpusets_enabled()) -+ if (!static_key_false(&cpusets_enabled_key)) - return false; - - return read_seqcount_retry(¤t->mems_allowed_seq, seq); -diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h -index fdda45f26f75..22f442ab85f9 100644 ---- a/include/target/iscsi/iscsi_target_core.h -+++ b/include/target/iscsi/iscsi_target_core.h -@@ -784,6 +784,7 @@ struct iscsi_np { - int np_sock_type; - enum np_thread_state_table np_thread_state; - bool enabled; -+ atomic_t np_reset_count; - enum iscsi_timer_flags_table np_login_timer_flags; - u32 np_exports; - enum np_flags_table np_flags; -diff --git a/kernel/cpuset.c b/kernel/cpuset.c -index 3b5e5430f5d0..8ccd66a97c8b 100644 ---- a/kernel/cpuset.c -+++ b/kernel/cpuset.c -@@ -60,6 +60,7 @@ - #include - #include - -+struct static_key cpusets_pre_enable_key __read_mostly = STATIC_KEY_INIT_FALSE; - struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE; - - /* See "Frequency meter" comments, below. */ -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index f9d648fce8cd..53286b2f5b1c 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -6804,7 +6804,7 @@ int alloc_contig_range(unsigned long start, unsigned long end, - - /* Make sure the range is really isolated. */ - if (test_pages_isolated(outer_start, end, false)) { -- pr_info("%s: [%lx, %lx) PFNs busy\n", -+ pr_info_ratelimited("%s: [%lx, %lx) PFNs busy\n", - __func__, outer_start, end); - ret = -EBUSY; - goto done; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.83-84.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.83-84.patch deleted file mode 100644 index 74a42d331..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.83-84.patch +++ /dev/null @@ -1,761 +0,0 @@ -diff --git a/Makefile b/Makefile -index 7f67b35caf99..9d77ac063ec0 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 83 -+SUBLEVEL = 84 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h -index 9e11dbe1cec3..329c127e13dc 100644 ---- a/arch/arm64/include/asm/elf.h -+++ b/arch/arm64/include/asm/elf.h -@@ -121,10 +121,10 @@ typedef struct user_fpsimd_state elf_fpregset_t; - - /* - * This is the base location for PIE (ET_DYN with INTERP) loads. On -- * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * 64-bit, this is above 4GB to leave the entire 32-bit address - * space open for things that want to use the area for 32-bit pointers. - */ --#define ELF_ET_DYN_BASE 0x100000000UL -+#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3) - - /* - * When the program starts, a1 contains a pointer to a function to be -diff --git a/arch/x86/crypto/sha1_avx2_x86_64_asm.S b/arch/x86/crypto/sha1_avx2_x86_64_asm.S -index 1cd792db15ef..1eab79c9ac48 100644 ---- a/arch/x86/crypto/sha1_avx2_x86_64_asm.S -+++ b/arch/x86/crypto/sha1_avx2_x86_64_asm.S -@@ -117,11 +117,10 @@ - .set T1, REG_T1 - .endm - --#define K_BASE %r8 - #define HASH_PTR %r9 -+#define BLOCKS_CTR %r8 - #define BUFFER_PTR %r10 - #define BUFFER_PTR2 %r13 --#define BUFFER_END %r11 - - #define PRECALC_BUF %r14 - #define WK_BUF %r15 -@@ -205,14 +204,14 @@ - * blended AVX2 and ALU instruction scheduling - * 1 vector iteration per 8 rounds - */ -- vmovdqu ((i * 2) + PRECALC_OFFSET)(BUFFER_PTR), W_TMP -+ vmovdqu (i * 2)(BUFFER_PTR), W_TMP - .elseif ((i & 7) == 1) -- vinsertf128 $1, (((i-1) * 2)+PRECALC_OFFSET)(BUFFER_PTR2),\ -+ vinsertf128 $1, ((i-1) * 2)(BUFFER_PTR2),\ - WY_TMP, WY_TMP - .elseif ((i & 7) == 2) - vpshufb YMM_SHUFB_BSWAP, WY_TMP, WY - .elseif ((i & 7) == 4) -- vpaddd K_XMM(K_BASE), WY, WY_TMP -+ vpaddd K_XMM + K_XMM_AR(%rip), WY, WY_TMP - .elseif ((i & 7) == 7) - vmovdqu WY_TMP, PRECALC_WK(i&~7) - -@@ -255,7 +254,7 @@ - vpxor WY, WY_TMP, WY_TMP - .elseif ((i & 7) == 7) - vpxor WY_TMP2, WY_TMP, WY -- vpaddd K_XMM(K_BASE), WY, WY_TMP -+ vpaddd K_XMM + K_XMM_AR(%rip), WY, WY_TMP - vmovdqu WY_TMP, PRECALC_WK(i&~7) - - PRECALC_ROTATE_WY -@@ -291,7 +290,7 @@ - vpsrld $30, WY, WY - vpor WY, WY_TMP, WY - .elseif ((i & 7) == 7) -- vpaddd K_XMM(K_BASE), WY, WY_TMP -+ vpaddd K_XMM + K_XMM_AR(%rip), WY, WY_TMP - vmovdqu WY_TMP, PRECALC_WK(i&~7) - - PRECALC_ROTATE_WY -@@ -446,6 +445,16 @@ - - .endm - -+/* Add constant only if (%2 > %3) condition met (uses RTA as temp) -+ * %1 + %2 >= %3 ? %4 : 0 -+ */ -+.macro ADD_IF_GE a, b, c, d -+ mov \a, RTA -+ add $\d, RTA -+ cmp $\c, \b -+ cmovge RTA, \a -+.endm -+ - /* - * macro implements 80 rounds of SHA-1, for multiple blocks with s/w pipelining - */ -@@ -463,13 +472,16 @@ - lea (2*4*80+32)(%rsp), WK_BUF - - # Precalc WK for first 2 blocks -- PRECALC_OFFSET = 0 -+ ADD_IF_GE BUFFER_PTR2, BLOCKS_CTR, 2, 64 - .set i, 0 - .rept 160 - PRECALC i - .set i, i + 1 - .endr -- PRECALC_OFFSET = 128 -+ -+ /* Go to next block if needed */ -+ ADD_IF_GE BUFFER_PTR, BLOCKS_CTR, 3, 128 -+ ADD_IF_GE BUFFER_PTR2, BLOCKS_CTR, 4, 128 - xchg WK_BUF, PRECALC_BUF - - .align 32 -@@ -479,8 +491,8 @@ _loop: - * we use K_BASE value as a signal of a last block, - * it is set below by: cmovae BUFFER_PTR, K_BASE - */ -- cmp K_BASE, BUFFER_PTR -- jne _begin -+ test BLOCKS_CTR, BLOCKS_CTR -+ jnz _begin - .align 32 - jmp _end - .align 32 -@@ -512,10 +524,10 @@ _loop0: - .set j, j+2 - .endr - -- add $(2*64), BUFFER_PTR /* move to next odd-64-byte block */ -- cmp BUFFER_END, BUFFER_PTR /* is current block the last one? */ -- cmovae K_BASE, BUFFER_PTR /* signal the last iteration smartly */ -- -+ /* Update Counter */ -+ sub $1, BLOCKS_CTR -+ /* Move to the next block only if needed*/ -+ ADD_IF_GE BUFFER_PTR, BLOCKS_CTR, 4, 128 - /* - * rounds - * 60,62,64,66,68 -@@ -532,8 +544,8 @@ _loop0: - UPDATE_HASH 12(HASH_PTR), D - UPDATE_HASH 16(HASH_PTR), E - -- cmp K_BASE, BUFFER_PTR /* is current block the last one? */ -- je _loop -+ test BLOCKS_CTR, BLOCKS_CTR -+ jz _loop - - mov TB, B - -@@ -575,10 +587,10 @@ _loop2: - .set j, j+2 - .endr - -- add $(2*64), BUFFER_PTR2 /* move to next even-64-byte block */ -- -- cmp BUFFER_END, BUFFER_PTR2 /* is current block the last one */ -- cmovae K_BASE, BUFFER_PTR /* signal the last iteration smartly */ -+ /* update counter */ -+ sub $1, BLOCKS_CTR -+ /* Move to the next block only if needed*/ -+ ADD_IF_GE BUFFER_PTR2, BLOCKS_CTR, 4, 128 - - jmp _loop3 - _loop3: -@@ -641,19 +653,12 @@ _loop3: - - avx2_zeroupper - -- lea K_XMM_AR(%rip), K_BASE -- -+ /* Setup initial values */ - mov CTX, HASH_PTR - mov BUF, BUFFER_PTR -- lea 64(BUF), BUFFER_PTR2 -- -- shl $6, CNT /* mul by 64 */ -- add BUF, CNT -- add $64, CNT -- mov CNT, BUFFER_END - -- cmp BUFFER_END, BUFFER_PTR2 -- cmovae K_BASE, BUFFER_PTR2 -+ mov BUF, BUFFER_PTR2 -+ mov CNT, BLOCKS_CTR - - xmm_mov BSWAP_SHUFB_CTL(%rip), YMM_SHUFB_BSWAP - -diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c -index 7de207a11014..dd14616b7739 100644 ---- a/arch/x86/crypto/sha1_ssse3_glue.c -+++ b/arch/x86/crypto/sha1_ssse3_glue.c -@@ -201,7 +201,7 @@ asmlinkage void sha1_transform_avx2(u32 *digest, const char *data, - - static bool avx2_usable(void) - { -- if (false && avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) -+ if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) - && boot_cpu_has(X86_FEATURE_BMI1) - && boot_cpu_has(X86_FEATURE_BMI2)) - return true; -diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S -index a55697d19824..cc0f2f5da19b 100644 ---- a/arch/x86/entry/entry_64.S -+++ b/arch/x86/entry/entry_64.S -@@ -1190,6 +1190,8 @@ ENTRY(nmi) - * other IST entries. - */ - -+ ASM_CLAC -+ - /* Use %rdx as our temp variable throughout */ - pushq %rdx - -diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h -index 07cf288b692e..bcd3d6199464 100644 ---- a/arch/x86/include/asm/elf.h -+++ b/arch/x86/include/asm/elf.h -@@ -247,11 +247,11 @@ extern int force_personality32; - - /* - * This is the base location for PIE (ET_DYN with INTERP) loads. On -- * 64-bit, this is raised to 4GB to leave the entire 32-bit address -+ * 64-bit, this is above 4GB to leave the entire 32-bit address - * space open for things that want to use the area for 32-bit pointers. - */ - #define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \ -- 0x100000000UL) -+ (TASK_SIZE / 3 * 2)) - - /* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. This could be done in user space, -diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c -index 8900400230c6..2cdae69d7e0b 100644 ---- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c -+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c -@@ -153,7 +153,7 @@ static void __intel_pmu_lbr_enable(bool pmi) - */ - if (cpuc->lbr_sel) - lbr_select = cpuc->lbr_sel->config; -- if (!pmi) -+ if (!pmi && cpuc->lbr_sel) - wrmsrl(MSR_LBR_SELECT, lbr_select); - - rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); -@@ -432,8 +432,10 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) - int out = 0; - int num = x86_pmu.lbr_nr; - -- if (cpuc->lbr_sel->config & LBR_CALL_STACK) -- num = tos; -+ if (cpuc->lbr_sel) { -+ if (cpuc->lbr_sel->config & LBR_CALL_STACK) -+ num = tos; -+ } - - for (i = 0; i < num; i++) { - unsigned long lbr_idx = (tos - i) & mask; -diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c -index da5458dfb1e3..98d4e515587a 100644 ---- a/drivers/input/mouse/elan_i2c_core.c -+++ b/drivers/input/mouse/elan_i2c_core.c -@@ -1235,6 +1235,10 @@ static const struct acpi_device_id elan_acpi_id[] = { - { "ELAN0100", 0 }, - { "ELAN0600", 0 }, - { "ELAN0605", 0 }, -+ { "ELAN0608", 0 }, -+ { "ELAN0605", 0 }, -+ { "ELAN0609", 0 }, -+ { "ELAN060B", 0 }, - { "ELAN1000", 0 }, - { } - }; -diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c -index 37199b9b2cfa..831a195cb806 100644 ---- a/drivers/irqchip/irq-atmel-aic-common.c -+++ b/drivers/irqchip/irq-atmel-aic-common.c -@@ -148,9 +148,9 @@ void __init aic_common_rtc_irq_fixup(struct device_node *root) - struct device_node *np; - void __iomem *regs; - -- np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc"); -+ np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-rtc"); - if (!np) -- np = of_find_compatible_node(root, NULL, -+ np = of_find_compatible_node(NULL, NULL, - "atmel,at91sam9x5-rtc"); - - if (!np) -@@ -202,7 +202,6 @@ void __init aic_common_irq_fixup(const struct of_device_id *matches) - return; - - match = of_match_node(matches, root); -- of_node_put(root); - - if (match) { - void (*fixup)(struct device_node *) = match->data; -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index 582d8f0c6266..958af3b1af7f 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -707,6 +707,7 @@ static const struct usb_device_id products[] = { - {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ - {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ - {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ -+ {QMI_FIXED_INTF(0x2001, 0x7e35, 4)}, /* D-Link DWM-222 */ - {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ - {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ - {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ -diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c -index 7b0ca1551d7b..005ea632ba53 100644 ---- a/drivers/parisc/dino.c -+++ b/drivers/parisc/dino.c -@@ -954,7 +954,7 @@ static int __init dino_probe(struct parisc_device *dev) - - dino_dev->hba.dev = dev; - dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096); -- dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ -+ dino_dev->hba.lmmio_space_offset = PCI_F_EXTEND; - spin_lock_init(&dino_dev->dinosaur_pen); - dino_dev->hba.iommu = ccio_get_iommu(dev); - -diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c -index 2776cfe64c09..ef9cf4a21afe 100644 ---- a/drivers/usb/core/usb-acpi.c -+++ b/drivers/usb/core/usb-acpi.c -@@ -127,6 +127,22 @@ out: - */ - #define USB_ACPI_LOCATION_VALID (1 << 31) - -+static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent, -+ int raw) -+{ -+ struct acpi_device *adev; -+ -+ if (!parent) -+ return NULL; -+ -+ list_for_each_entry(adev, &parent->children, node) { -+ if (acpi_device_adr(adev) == raw) -+ return adev; -+ } -+ -+ return acpi_find_child_device(parent, raw, false); -+} -+ - static struct acpi_device *usb_acpi_find_companion(struct device *dev) - { - struct usb_device *udev; -@@ -174,8 +190,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) - int raw; - - raw = usb_hcd_find_raw_port_number(hcd, port1); -- adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), -- raw, false); -+ -+ adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev), -+ raw); -+ - if (!adev) - return NULL; - } else { -@@ -186,7 +204,9 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) - return NULL; - - acpi_bus_get_device(parent_handle, &adev); -- adev = acpi_find_child_device(adev, port1, false); -+ -+ adev = usb_acpi_find_port(adev, port1); -+ - if (!adev) - return NULL; - } -diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c -index 4da69dbf7dca..1bdd02a6d6ac 100644 ---- a/drivers/xen/biomerge.c -+++ b/drivers/xen/biomerge.c -@@ -10,8 +10,7 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, - unsigned long bfn1 = pfn_to_bfn(page_to_pfn(vec1->bv_page)); - unsigned long bfn2 = pfn_to_bfn(page_to_pfn(vec2->bv_page)); - -- return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) && -- ((bfn1 == bfn2) || ((bfn1+1) == bfn2)); -+ return bfn1 + PFN_DOWN(vec1->bv_offset + vec1->bv_len) == bfn2; - #else - /* - * XXX: Add support for merging bio_vec when using different page -diff --git a/include/linux/pid.h b/include/linux/pid.h -index 23705a53abba..97b745ddece5 100644 ---- a/include/linux/pid.h -+++ b/include/linux/pid.h -@@ -8,7 +8,9 @@ enum pid_type - PIDTYPE_PID, - PIDTYPE_PGID, - PIDTYPE_SID, -- PIDTYPE_MAX -+ PIDTYPE_MAX, -+ /* only valid to __task_pid_nr_ns() */ -+ __PIDTYPE_TGID - }; - - /* -diff --git a/include/linux/sched.h b/include/linux/sched.h -index eff7c1fad26f..e887c8d6f395 100644 ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1949,31 +1949,8 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk) - return tsk->tgid; - } - --pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); -- --static inline pid_t task_tgid_vnr(struct task_struct *tsk) --{ -- return pid_vnr(task_tgid(tsk)); --} -- - - static inline int pid_alive(const struct task_struct *p); --static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) --{ -- pid_t pid = 0; -- -- rcu_read_lock(); -- if (pid_alive(tsk)) -- pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); -- rcu_read_unlock(); -- -- return pid; --} -- --static inline pid_t task_ppid_nr(const struct task_struct *tsk) --{ -- return task_ppid_nr_ns(tsk, &init_pid_ns); --} - - static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, - struct pid_namespace *ns) -@@ -1998,6 +1975,33 @@ static inline pid_t task_session_vnr(struct task_struct *tsk) - return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL); - } - -+static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) -+{ -+ return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns); -+} -+ -+static inline pid_t task_tgid_vnr(struct task_struct *tsk) -+{ -+ return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL); -+} -+ -+static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) -+{ -+ pid_t pid = 0; -+ -+ rcu_read_lock(); -+ if (pid_alive(tsk)) -+ pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); -+ rcu_read_unlock(); -+ -+ return pid; -+} -+ -+static inline pid_t task_ppid_nr(const struct task_struct *tsk) -+{ -+ return task_ppid_nr_ns(tsk, &init_pid_ns); -+} -+ - /* obsolete, do not use */ - static inline pid_t task_pgrp_nr(struct task_struct *tsk) - { -diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c -index 939945a5649c..a162661c9d60 100644 ---- a/kernel/audit_watch.c -+++ b/kernel/audit_watch.c -@@ -457,13 +457,15 @@ void audit_remove_watch_rule(struct audit_krule *krule) - list_del(&krule->rlist); - - if (list_empty(&watch->rules)) { -+ /* -+ * audit_remove_watch() drops our reference to 'parent' which -+ * can get freed. Grab our own reference to be safe. -+ */ -+ audit_get_parent(parent); - audit_remove_watch(watch); -- -- if (list_empty(&parent->watches)) { -- audit_get_parent(parent); -+ if (list_empty(&parent->watches)) - fsnotify_destroy_mark(&parent->mark, audit_watch_group); -- audit_put_parent(parent); -- } -+ audit_put_parent(parent); - } - } - -diff --git a/kernel/pid.c b/kernel/pid.c -index 78b3d9f80d44..b17263be9082 100644 ---- a/kernel/pid.c -+++ b/kernel/pid.c -@@ -526,8 +526,11 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, - if (!ns) - ns = task_active_pid_ns(current); - if (likely(pid_alive(task))) { -- if (type != PIDTYPE_PID) -+ if (type != PIDTYPE_PID) { -+ if (type == __PIDTYPE_TGID) -+ type = PIDTYPE_PID; - task = task->group_leader; -+ } - nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns); - } - rcu_read_unlock(); -@@ -536,12 +539,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, - } - EXPORT_SYMBOL(__task_pid_nr_ns); - --pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) --{ -- return pid_nr_ns(task_tgid(tsk), ns); --} --EXPORT_SYMBOL(task_tgid_nr_ns); -- - struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) - { - return ns_of_pid(task_pid(tsk)); -diff --git a/mm/mempolicy.c b/mm/mempolicy.c -index e09b1a0e2cfe..c947014d128a 100644 ---- a/mm/mempolicy.c -+++ b/mm/mempolicy.c -@@ -894,11 +894,6 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, - *policy |= (pol->flags & MPOL_MODE_FLAGS); - } - -- if (vma) { -- up_read(¤t->mm->mmap_sem); -- vma = NULL; -- } -- - err = 0; - if (nmask) { - if (mpol_store_user_nodemask(pol)) { -diff --git a/mm/migrate.c b/mm/migrate.c -index 72c09dea6526..afedcfab60e2 100644 ---- a/mm/migrate.c -+++ b/mm/migrate.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - -@@ -1483,7 +1484,6 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, - const int __user *, nodes, - int __user *, status, int, flags) - { -- const struct cred *cred = current_cred(), *tcred; - struct task_struct *task; - struct mm_struct *mm; - int err; -@@ -1507,14 +1507,9 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, - - /* - * Check if this process has the right to modify the specified -- * process. The right exists if the process has administrative -- * capabilities, superuser privileges or the same -- * userid as the target process. -+ * process. Use the regular "ptrace_may_access()" checks. - */ -- tcred = __task_cred(task); -- if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) && -- !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) && -- !capable(CAP_SYS_NICE)) { -+ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) { - rcu_read_unlock(); - err = -EPERM; - goto out; -diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c -index 1a9545965c0d..531ca55f1af6 100644 ---- a/net/netfilter/nf_conntrack_extend.c -+++ b/net/netfilter/nf_conntrack_extend.c -@@ -53,7 +53,11 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, - - rcu_read_lock(); - t = rcu_dereference(nf_ct_ext_types[id]); -- BUG_ON(t == NULL); -+ if (!t) { -+ rcu_read_unlock(); -+ return NULL; -+ } -+ - off = ALIGN(sizeof(struct nf_ct_ext), t->align); - len = off + t->len + var_alloc_len; - alloc_size = t->alloc_size + var_alloc_len; -@@ -88,7 +92,10 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id, - - rcu_read_lock(); - t = rcu_dereference(nf_ct_ext_types[id]); -- BUG_ON(t == NULL); -+ if (!t) { -+ rcu_read_unlock(); -+ return NULL; -+ } - - newoff = ALIGN(old->len, t->align); - newlen = newoff + t->len + var_alloc_len; -@@ -186,6 +193,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) - RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL); - update_alloc_size(type); - mutex_unlock(&nf_ct_ext_type_mutex); -- rcu_barrier(); /* Wait for completion of call_rcu()'s */ -+ synchronize_rcu(); - } - EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); -diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c -index c67f9c212dd1..e326c1d80416 100644 ---- a/sound/core/seq/seq_clientmgr.c -+++ b/sound/core/seq/seq_clientmgr.c -@@ -1530,19 +1530,14 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - void __user *arg) - { - struct snd_seq_queue_info info; -- int result; - struct snd_seq_queue *q; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - -- result = snd_seq_queue_alloc(client->number, info.locked, info.flags); -- if (result < 0) -- return result; -- -- q = queueptr(result); -- if (q == NULL) -- return -EINVAL; -+ q = snd_seq_queue_alloc(client->number, info.locked, info.flags); -+ if (IS_ERR(q)) -+ return PTR_ERR(q); - - info.queue = q->queue; - info.locked = q->locked; -@@ -1552,7 +1547,7 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - if (! info.name[0]) - snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); - strlcpy(q->name, info.name, sizeof(q->name)); -- queuefree(q); -+ snd_use_lock_free(&q->use_lock); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; -diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c -index 450c5187eecb..79e0c5604ef8 100644 ---- a/sound/core/seq/seq_queue.c -+++ b/sound/core/seq/seq_queue.c -@@ -184,22 +184,26 @@ void __exit snd_seq_queues_delete(void) - static void queue_use(struct snd_seq_queue *queue, int client, int use); - - /* allocate a new queue - -- * return queue index value or negative value for error -+ * return pointer to new queue or ERR_PTR(-errno) for error -+ * The new queue's use_lock is set to 1. It is the caller's responsibility to -+ * call snd_use_lock_free(&q->use_lock). - */ --int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) -+struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) - { - struct snd_seq_queue *q; - - q = queue_new(client, locked); - if (q == NULL) -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - q->info_flags = info_flags; - queue_use(q, client, 1); -+ snd_use_lock_use(&q->use_lock); - if (queue_list_add(q) < 0) { -+ snd_use_lock_free(&q->use_lock); - queue_delete(q); -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - } -- return q->queue; -+ return q; - } - - /* delete a queue - queue must be owned by the client */ -diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h -index 30c8111477f6..719093489a2c 100644 ---- a/sound/core/seq/seq_queue.h -+++ b/sound/core/seq/seq_queue.h -@@ -71,7 +71,7 @@ void snd_seq_queues_delete(void); - - - /* create new queue (constructor) */ --int snd_seq_queue_alloc(int client, int locked, unsigned int flags); -+struct snd_seq_queue *snd_seq_queue_alloc(int client, int locked, unsigned int flags); - - /* delete queue (destructor) */ - int snd_seq_queue_delete(int client, int queueid); -diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c -index 499b03c8281d..696de5ac69be 100644 ---- a/sound/usb/mixer.c -+++ b/sound/usb/mixer.c -@@ -541,6 +541,8 @@ int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, - - if (size < sizeof(scale)) - return -ENOMEM; -+ if (cval->min_mute) -+ scale[0] = SNDRV_CTL_TLVT_DB_MINMAX_MUTE; - scale[2] = cval->dBmin; - scale[3] = cval->dBmax; - if (copy_to_user(_tlv, scale, sizeof(scale))) -diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h -index 3417ef347e40..2b4b067646ab 100644 ---- a/sound/usb/mixer.h -+++ b/sound/usb/mixer.h -@@ -64,6 +64,7 @@ struct usb_mixer_elem_info { - int cached; - int cache_val[MAX_CHANNELS]; - u8 initialized; -+ u8 min_mute; - void *private_data; - }; - -diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c -index 04991b009132..5d2fc5f58bfe 100644 ---- a/sound/usb/mixer_quirks.c -+++ b/sound/usb/mixer_quirks.c -@@ -1873,6 +1873,12 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, - if (unitid == 7 && cval->control == UAC_FU_VOLUME) - snd_dragonfly_quirk_db_scale(mixer, cval, kctl); - break; -+ /* lowest playback value is muted on C-Media devices */ -+ case USB_ID(0x0d8c, 0x000c): -+ case USB_ID(0x0d8c, 0x0014): -+ if (strstr(kctl->id.name, "Playback")) -+ cval->min_mute = 1; -+ break; - } - } - -diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c -index 29f38e2b4ca9..1cc20d138dae 100644 ---- a/sound/usb/quirks.c -+++ b/sound/usb/quirks.c -@@ -1143,6 +1143,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) - case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ - case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ - case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ -+ case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ - case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ - case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */ - case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */ diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.84-85.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.84-85.patch deleted file mode 100644 index d88ef90b4..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.84-85.patch +++ /dev/null @@ -1,1498 +0,0 @@ -diff --git a/Makefile b/Makefile -index 9d77ac063ec0..0f3d843f42a7 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 84 -+SUBLEVEL = 85 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h -index 210ef3e72332..0ddd7144c492 100644 ---- a/arch/arc/include/asm/cache.h -+++ b/arch/arc/include/asm/cache.h -@@ -88,7 +88,9 @@ extern int ioc_exists; - #define ARC_REG_SLC_FLUSH 0x904 - #define ARC_REG_SLC_INVALIDATE 0x905 - #define ARC_REG_SLC_RGN_START 0x914 -+#define ARC_REG_SLC_RGN_START1 0x915 - #define ARC_REG_SLC_RGN_END 0x916 -+#define ARC_REG_SLC_RGN_END1 0x917 - - /* Bit val in SLC_CONTROL */ - #define SLC_CTRL_IM 0x040 -diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c -index d81b6d7e11e7..9a84cbdd44b0 100644 ---- a/arch/arc/mm/cache.c -+++ b/arch/arc/mm/cache.c -@@ -543,6 +543,7 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) - static DEFINE_SPINLOCK(lock); - unsigned long flags; - unsigned int ctrl; -+ phys_addr_t end; - - spin_lock_irqsave(&lock, flags); - -@@ -572,8 +573,16 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op) - * END needs to be setup before START (latter triggers the operation) - * END can't be same as START, so add (l2_line_sz - 1) to sz - */ -- write_aux_reg(ARC_REG_SLC_RGN_END, (paddr + sz + l2_line_sz - 1)); -- write_aux_reg(ARC_REG_SLC_RGN_START, paddr); -+ end = paddr + sz + l2_line_sz - 1; -+ if (is_pae40_enabled()) -+ write_aux_reg(ARC_REG_SLC_RGN_END1, upper_32_bits(end)); -+ -+ write_aux_reg(ARC_REG_SLC_RGN_END, lower_32_bits(end)); -+ -+ if (is_pae40_enabled()) -+ write_aux_reg(ARC_REG_SLC_RGN_START1, upper_32_bits(paddr)); -+ -+ write_aux_reg(ARC_REG_SLC_RGN_START, lower_32_bits(paddr)); - - while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY); - -diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c -index eac4f3b02df9..bb81cd05f0bc 100644 ---- a/drivers/acpi/apei/ghes.c -+++ b/drivers/acpi/apei/ghes.c -@@ -1067,6 +1067,7 @@ static int ghes_remove(struct platform_device *ghes_dev) - if (list_empty(&ghes_sci)) - unregister_acpi_hed_notifier(&ghes_notifier_sci); - mutex_unlock(&ghes_list_mutex); -+ synchronize_rcu(); - break; - case ACPI_HEST_NOTIFY_NMI: - ghes_nmi_remove(ghes); -diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c -index ccdc8db16bb8..fa2cf2dc4e33 100644 ---- a/drivers/acpi/ioapic.c -+++ b/drivers/acpi/ioapic.c -@@ -45,6 +45,12 @@ static acpi_status setup_res(struct acpi_resource *acpi_res, void *data) - struct resource *res = data; - struct resource_win win; - -+ /* -+ * We might assign this to 'res' later, make sure all pointers are -+ * cleared before the resource is added to the global list -+ */ -+ memset(&win, 0, sizeof(win)); -+ - res->flags = 0; - if (acpi_dev_filter_resource_type(acpi_res, IORESOURCE_MEM) == 0) - return AE_OK; -diff --git a/drivers/android/binder.c b/drivers/android/binder.c -index 47ddfefe2443..5531f020e561 100644 ---- a/drivers/android/binder.c -+++ b/drivers/android/binder.c -@@ -1718,8 +1718,12 @@ static void binder_transaction(struct binder_proc *proc, - list_add_tail(&t->work.entry, target_list); - tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE; - list_add_tail(&tcomplete->entry, &thread->todo); -- if (target_wait) -- wake_up_interruptible(target_wait); -+ if (target_wait) { -+ if (reply || !(t->flags & TF_ONE_WAY)) -+ wake_up_interruptible_sync(target_wait); -+ else -+ wake_up_interruptible(target_wait); -+ } - return; - - err_get_unused_fd_failed: -@@ -2865,7 +2869,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) - const char *failure_string; - struct binder_buffer *buffer; - -- if (proc->tsk != current) -+ if (proc->tsk != current->group_leader) - return -EINVAL; - - if ((vma->vm_end - vma->vm_start) > SZ_4M) -@@ -2966,8 +2970,8 @@ static int binder_open(struct inode *nodp, struct file *filp) - proc = kzalloc(sizeof(*proc), GFP_KERNEL); - if (proc == NULL) - return -ENOMEM; -- get_task_struct(current); -- proc->tsk = current; -+ get_task_struct(current->group_leader); -+ proc->tsk = current->group_leader; - INIT_LIST_HEAD(&proc->todo); - init_waitqueue_head(&proc->wait); - proc->default_priority = task_nice(current); -diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c -index 6253775b8d9c..50d74e5ce41b 100644 ---- a/drivers/gpu/drm/drm_atomic.c -+++ b/drivers/gpu/drm/drm_atomic.c -@@ -1247,6 +1247,9 @@ int drm_atomic_check_only(struct drm_atomic_state *state) - if (config->funcs->atomic_check) - ret = config->funcs->atomic_check(state->dev, state); - -+ if (ret) -+ return ret; -+ - if (!state->allow_modeset) { - for_each_crtc_in_state(state, crtc, crtc_state, i) { - if (drm_atomic_crtc_needs_modeset(crtc_state)) { -@@ -1257,7 +1260,7 @@ int drm_atomic_check_only(struct drm_atomic_state *state) - } - } - -- return ret; -+ return 0; - } - EXPORT_SYMBOL(drm_atomic_check_only); - -diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c -index b205224f1a44..9147113139be 100644 ---- a/drivers/gpu/drm/drm_gem.c -+++ b/drivers/gpu/drm/drm_gem.c -@@ -715,13 +715,13 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) - struct drm_gem_object *obj = ptr; - struct drm_device *dev = obj->dev; - -+ if (dev->driver->gem_close_object) -+ dev->driver->gem_close_object(obj, file_priv); -+ - if (drm_core_check_feature(dev, DRIVER_PRIME)) - drm_gem_remove_prime_handles(obj, file_priv); - drm_vma_node_revoke(&obj->vma_node, file_priv->filp); - -- if (dev->driver->gem_close_object) -- dev->driver->gem_close_object(obj, file_priv); -- - drm_gem_object_handle_unreference_unlocked(obj); - - return 0; -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -index 9255b9c096b6..9befd624a5f0 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c -@@ -148,8 +148,8 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) - rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0); - - /* Signal polarities */ -- value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL) -- | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL) -+ value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0) -+ | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0) - | DSMR_DIPM_DE | DSMR_CSPM; - rcar_du_crtc_write(rcrtc, DSMR, value); - -@@ -171,7 +171,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) - mode->crtc_vsync_start - 1); - rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1); - -- rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start); -+ rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start - 1); - rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay); - } - -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c -index 46429c4be8e5..2b75a4891dec 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c -@@ -642,13 +642,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, - } - - ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector); -- of_node_put(encoder); -- of_node_put(connector); -- - if (ret && ret != -EPROBE_DEFER) - dev_warn(rcdu->dev, -- "failed to initialize encoder %s (%d), skipping\n", -- encoder->full_name, ret); -+ "failed to initialize encoder %s on output %u (%d), skipping\n", -+ of_node_full_name(encoder), output, ret); -+ -+ of_node_put(encoder); -+ of_node_put(connector); - - return ret; - } -diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c -index 85043c5bad03..873e04aa9352 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c -+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c -@@ -56,11 +56,11 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, - return ret; - - /* PLL clock configuration */ -- if (freq <= 38000) -+ if (freq < 39000) - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; -- else if (freq <= 60000) -+ else if (freq < 61000) - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; -- else if (freq <= 121000) -+ else if (freq < 121000) - pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M; - else - pllcr = LVDPLLCR_PLLDLYCNT_150M; -@@ -102,7 +102,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds, - /* Turn the PLL on, wait for the startup delay, and turn the output - * on. - */ -- lvdcr0 |= LVDCR0_PLLEN; -+ lvdcr0 |= LVDCR0_PLLON; - rcar_lvds_write(lvds, LVDCR0, lvdcr0); - - usleep_range(100, 150); -diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h -index 77cf9289ab65..b1eafd097a79 100644 ---- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h -+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h -@@ -18,7 +18,7 @@ - #define LVDCR0_DMD (1 << 12) - #define LVDCR0_LVMD_MASK (0xf << 8) - #define LVDCR0_LVMD_SHIFT 8 --#define LVDCR0_PLLEN (1 << 4) -+#define LVDCR0_PLLON (1 << 4) - #define LVDCR0_BEN (1 << 2) - #define LVDCR0_LVEN (1 << 1) - #define LVDCR0_LVRES (1 << 0) -diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c -index 6b00061c3746..a2ae2213ef3e 100644 ---- a/drivers/i2c/busses/i2c-designware-platdrv.c -+++ b/drivers/i2c/busses/i2c-designware-platdrv.c -@@ -294,7 +294,7 @@ static void dw_i2c_plat_complete(struct device *dev) - #endif - - #ifdef CONFIG_PM --static int dw_i2c_plat_suspend(struct device *dev) -+static int dw_i2c_plat_runtime_suspend(struct device *dev) - { - struct platform_device *pdev = to_platform_device(dev); - struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); -@@ -318,11 +318,21 @@ static int dw_i2c_plat_resume(struct device *dev) - return 0; - } - -+#ifdef CONFIG_PM_SLEEP -+static int dw_i2c_plat_suspend(struct device *dev) -+{ -+ pm_runtime_resume(dev); -+ return dw_i2c_plat_runtime_suspend(dev); -+} -+#endif -+ - static const struct dev_pm_ops dw_i2c_dev_pm_ops = { - .prepare = dw_i2c_plat_prepare, - .complete = dw_i2c_plat_complete, - SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) -- SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL) -+ SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, -+ dw_i2c_plat_resume, -+ NULL) - }; - - #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) -diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c -index 0a86ef43e781..a8db38db622e 100644 ---- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c -+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c -@@ -36,8 +36,6 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) - s32 poll_value = 0; - - if (state) { -- if (!atomic_read(&st->user_requested_state)) -- return 0; - if (sensor_hub_device_open(st->hsdev)) - return -EIO; - -@@ -84,6 +82,9 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) - &report_val); - } - -+ pr_debug("HID_SENSOR %s set power_state %d report_state %d\n", -+ st->pdev->name, state_val, report_val); -+ - sensor_hub_get_feature(st->hsdev, st->power_state.report_id, - st->power_state.index, - sizeof(state_val), &state_val); -@@ -107,6 +108,7 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) - ret = pm_runtime_get_sync(&st->pdev->dev); - else { - pm_runtime_mark_last_busy(&st->pdev->dev); -+ pm_runtime_use_autosuspend(&st->pdev->dev); - ret = pm_runtime_put_autosuspend(&st->pdev->dev); - } - if (ret < 0) { -@@ -175,8 +177,6 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, - /* Default to 3 seconds, but can be changed from sysfs */ - pm_runtime_set_autosuspend_delay(&attrb->pdev->dev, - 3000); -- pm_runtime_use_autosuspend(&attrb->pdev->dev); -- - return ret; - error_unreg_trigger: - iio_trigger_unregister(trig); -diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c -index 2485b88ee1b6..1880105cc8c4 100644 ---- a/drivers/iio/imu/adis16480.c -+++ b/drivers/iio/imu/adis16480.c -@@ -696,7 +696,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { - .gyro_max_val = IIO_RAD_TO_DEGREE(22500), - .gyro_max_scale = 450, - .accel_max_val = IIO_M_S_2_TO_G(12500), -- .accel_max_scale = 5, -+ .accel_max_scale = 10, - }, - [ADIS16485] = { - .channels = adis16485_channels, -diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c -index 98d4e515587a..681dce15fbc8 100644 ---- a/drivers/input/mouse/elan_i2c_core.c -+++ b/drivers/input/mouse/elan_i2c_core.c -@@ -1234,6 +1234,7 @@ static const struct acpi_device_id elan_acpi_id[] = { - { "ELAN0000", 0 }, - { "ELAN0100", 0 }, - { "ELAN0600", 0 }, -+ { "ELAN0602", 0 }, - { "ELAN0605", 0 }, - { "ELAN0608", 0 }, - { "ELAN0605", 0 }, -diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c -index 354d47ecd66a..ce6ff9b301bb 100644 ---- a/drivers/input/mouse/trackpoint.c -+++ b/drivers/input/mouse/trackpoint.c -@@ -265,7 +265,8 @@ static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *fir - if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) - return -1; - -- if (param[0] != TP_MAGIC_IDENT) -+ /* add new TP ID. */ -+ if (!(param[0] & TP_MAGIC_IDENT)) - return -1; - - if (firmware_id) -diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h -index 5617ed3a7d7a..88055755f82e 100644 ---- a/drivers/input/mouse/trackpoint.h -+++ b/drivers/input/mouse/trackpoint.h -@@ -21,8 +21,9 @@ - #define TP_COMMAND 0xE2 /* Commands start with this */ - - #define TP_READ_ID 0xE1 /* Sent for device identification */ --#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */ -+#define TP_MAGIC_IDENT 0x03 /* Sent after a TP_READ_ID followed */ - /* by the firmware ID */ -+ /* Firmware ID includes 0x1, 0x2, 0x3 */ - - - /* -diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h -index a2661381ddfc..d2774197fe58 100644 ---- a/drivers/misc/mei/hw-me-regs.h -+++ b/drivers/misc/mei/hw-me-regs.h -@@ -125,6 +125,11 @@ - #define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ - #define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ - -+#define MEI_DEV_ID_LBG 0xA1BA /* Lewisburg (SPT) */ -+ -+#define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */ -+#define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */ -+ - /* - * MEI HW Section - */ -diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c -index 01e20384ac44..adab5bbb642a 100644 ---- a/drivers/misc/mei/pci-me.c -+++ b/drivers/misc/mei/pci-me.c -@@ -86,10 +86,14 @@ static const struct pci_device_id mei_me_pci_tbl[] = { - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)}, -+ {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)}, - -+ {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)}, -+ {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)}, -+ - /* required last entry */ - {0, } - }; -diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c -index ecc6fb9ca92f..3bbdf60f8908 100644 ---- a/drivers/ntb/ntb_transport.c -+++ b/drivers/ntb/ntb_transport.c -@@ -599,7 +599,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt, - if (!mw->virt_addr) - return -ENOMEM; - -- if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count) -+ if (mw_num < qp_count % mw_count) - num_qps_mw = qp_count / mw_count + 1; - else - num_qps_mw = qp_count / mw_count; -@@ -947,7 +947,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt, - qp->event_handler = NULL; - ntb_qp_link_down_reset(qp); - -- if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count) -+ if (mw_num < qp_count % mw_count) - num_qps_mw = qp_count / mw_count + 1; - else - num_qps_mw = qp_count / mw_count; -@@ -1065,8 +1065,8 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) - qp_count = ilog2(qp_bitmap); - if (max_num_clients && max_num_clients < qp_count) - qp_count = max_num_clients; -- else if (mw_count < qp_count) -- qp_count = mw_count; -+ else if (nt->mw_count < qp_count) -+ qp_count = nt->mw_count; - - qp_bitmap &= BIT_ULL(qp_count) - 1; - -diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c -index 02c3feef4e36..c2d2c17550a7 100644 ---- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c -+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c -@@ -49,6 +49,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { - {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ - {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ - {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ -+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ - {} /* Terminating entry */ - }; - -diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c -index 26a3b389a265..fa8df3fef6fc 100644 ---- a/fs/cifs/dir.c -+++ b/fs/cifs/dir.c -@@ -183,15 +183,20 @@ cifs_bp_rename_retry: - } - - /* -+ * Don't allow path components longer than the server max. - * Don't allow the separator character in a path component. - * The VFS will not allow "/", but "\" is allowed by posix. - */ - static int --check_name(struct dentry *direntry) -+check_name(struct dentry *direntry, struct cifs_tcon *tcon) - { - struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); - int i; - -+ if (unlikely(direntry->d_name.len > -+ tcon->fsAttrInfo.MaxPathNameComponentLength)) -+ return -ENAMETOOLONG; -+ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { - for (i = 0; i < direntry->d_name.len; i++) { - if (direntry->d_name.name[i] == '\\') { -@@ -489,10 +494,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, - return finish_no_open(file, res); - } - -- rc = check_name(direntry); -- if (rc) -- return rc; -- - xid = get_xid(); - - cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n", -@@ -505,6 +506,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, - } - - tcon = tlink_tcon(tlink); -+ -+ rc = check_name(direntry, tcon); -+ if (rc) -+ goto out_free_xid; -+ - server = tcon->ses->server; - - if (server->ops->new_lease_key) -@@ -765,7 +771,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, - } - pTcon = tlink_tcon(tlink); - -- rc = check_name(direntry); -+ rc = check_name(direntry, pTcon); - if (rc) - goto lookup_out; - -diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c -index f4afa3b1cc56..6c484ddf26a9 100644 ---- a/fs/cifs/smb2pdu.c -+++ b/fs/cifs/smb2pdu.c -@@ -2768,8 +2768,8 @@ copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf, - kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) * - le32_to_cpu(pfs_inf->SectorsPerAllocationUnit); - kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits); -- kst->f_bfree = le64_to_cpu(pfs_inf->ActualAvailableAllocationUnits); -- kst->f_bavail = le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits); -+ kst->f_bfree = kst->f_bavail = -+ le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits); - return; - } - -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index 3f68a25f2169..544672b440de 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -129,7 +129,7 @@ static void next_decode_page(struct nfsd4_compoundargs *argp) - argp->p = page_address(argp->pagelist[0]); - argp->pagelist++; - if (argp->pagelen < PAGE_SIZE) { -- argp->end = argp->p + (argp->pagelen>>2); -+ argp->end = argp->p + XDR_QUADLEN(argp->pagelen); - argp->pagelen = 0; - } else { - argp->end = argp->p + (PAGE_SIZE>>2); -@@ -1246,9 +1246,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) - argp->pagelen -= pages * PAGE_SIZE; - len -= pages * PAGE_SIZE; - -- argp->p = (__be32 *)page_address(argp->pagelist[0]); -- argp->pagelist++; -- argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE); -+ next_decode_page(argp); - } - argp->p += XDR_QUADLEN(len); - -diff --git a/include/net/ip.h b/include/net/ip.h -index b450d8653b30..7476bb10ff37 100644 ---- a/include/net/ip.h -+++ b/include/net/ip.h -@@ -314,7 +314,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, - !forwarding) - return dst_mtu(dst); - -- return min(dst->dev->mtu, IP_MAX_MTU); -+ return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); - } - - static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) -@@ -327,7 +327,7 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) - return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); - } - -- return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU); -+ return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); - } - - u32 ip_idents_reserve(u32 hash, int segs); -diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h -index e5bba897d206..7a5d6a073165 100644 ---- a/include/net/sch_generic.h -+++ b/include/net/sch_generic.h -@@ -717,8 +717,11 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, - old = *pold; - *pold = new; - if (old != NULL) { -- qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog); -+ unsigned int qlen = old->q.qlen; -+ unsigned int backlog = old->qstats.backlog; -+ - qdisc_reset(old); -+ qdisc_tree_reduce_backlog(old, qlen, backlog); - } - sch_tree_unlock(sch); - -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 784ab8fe8714..3697063dd09a 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -8473,28 +8473,27 @@ SYSCALL_DEFINE5(perf_event_open, - goto err_context; - - /* -- * Do not allow to attach to a group in a different -- * task or CPU context: -+ * Make sure we're both events for the same CPU; -+ * grouping events for different CPUs is broken; since -+ * you can never concurrently schedule them anyhow. - */ -- if (move_group) { -- /* -- * Make sure we're both on the same task, or both -- * per-cpu events. -- */ -- if (group_leader->ctx->task != ctx->task) -- goto err_context; -+ if (group_leader->cpu != event->cpu) -+ goto err_context; - -- /* -- * Make sure we're both events for the same CPU; -- * grouping events for different CPUs is broken; since -- * you can never concurrently schedule them anyhow. -- */ -- if (group_leader->cpu != event->cpu) -- goto err_context; -- } else { -- if (group_leader->ctx != ctx) -- goto err_context; -- } -+ /* -+ * Make sure we're both on the same task, or both -+ * per-CPU events. -+ */ -+ if (group_leader->ctx->task != ctx->task) -+ goto err_context; -+ -+ /* -+ * Do not allow to attach to a group in a different task -+ * or CPU context. If we're moving SW events, we'll fix -+ * this up later, so allow that. -+ */ -+ if (!move_group && group_leader->ctx != ctx) -+ goto err_context; - - /* - * Only a group leader can be exclusive or pinned -diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c -index 6816302542b2..f0e5408499b6 100644 ---- a/kernel/trace/trace_events_filter.c -+++ b/kernel/trace/trace_events_filter.c -@@ -1979,6 +1979,10 @@ static int create_filter(struct trace_event_call *call, - if (err && set_str) - append_filter_err(ps, filter); - } -+ if (err && !set_str) { -+ free_event_filter(filter); -+ filter = NULL; -+ } - create_filter_finish(ps); - - *filterp = filter; -diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c -index 1641367e54ca..69f56073b337 100644 ---- a/net/bluetooth/bnep/core.c -+++ b/net/bluetooth/bnep/core.c -@@ -484,16 +484,16 @@ static int bnep_session(void *arg) - struct net_device *dev = s->dev; - struct sock *sk = s->sock->sk; - struct sk_buff *skb; -- wait_queue_t wait; -+ DEFINE_WAIT_FUNC(wait, woken_wake_function); - - BT_DBG(""); - - set_user_nice(current, -15); - -- init_waitqueue_entry(&wait, current); - add_wait_queue(sk_sleep(sk), &wait); - while (1) { -- set_current_state(TASK_INTERRUPTIBLE); -+ /* Ensure session->terminate is updated */ -+ smp_mb__before_atomic(); - - if (atomic_read(&s->terminate)) - break; -@@ -515,9 +515,8 @@ static int bnep_session(void *arg) - break; - netif_wake_queue(dev); - -- schedule(); -+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); - } -- __set_current_state(TASK_RUNNING); - remove_wait_queue(sk_sleep(sk), &wait); - - /* Cleanup session */ -@@ -663,7 +662,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) - s = __bnep_get_session(req->dst); - if (s) { - atomic_inc(&s->terminate); -- wake_up_process(s->task); -+ wake_up_interruptible(sk_sleep(s->sock->sk)); - } else - err = -ENOENT; - -diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c -index 298ed37010e6..3a39fd523e40 100644 ---- a/net/bluetooth/cmtp/core.c -+++ b/net/bluetooth/cmtp/core.c -@@ -281,16 +281,16 @@ static int cmtp_session(void *arg) - struct cmtp_session *session = arg; - struct sock *sk = session->sock->sk; - struct sk_buff *skb; -- wait_queue_t wait; -+ DEFINE_WAIT_FUNC(wait, woken_wake_function); - - BT_DBG("session %p", session); - - set_user_nice(current, -15); - -- init_waitqueue_entry(&wait, current); - add_wait_queue(sk_sleep(sk), &wait); - while (1) { -- set_current_state(TASK_INTERRUPTIBLE); -+ /* Ensure session->terminate is updated */ -+ smp_mb__before_atomic(); - - if (atomic_read(&session->terminate)) - break; -@@ -307,9 +307,8 @@ static int cmtp_session(void *arg) - - cmtp_process_transmit(session); - -- schedule(); -+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); - } -- __set_current_state(TASK_RUNNING); - remove_wait_queue(sk_sleep(sk), &wait); - - down_write(&cmtp_session_sem); -@@ -394,7 +393,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) - err = cmtp_attach_device(session); - if (err < 0) { - atomic_inc(&session->terminate); -- wake_up_process(session->task); -+ wake_up_interruptible(sk_sleep(session->sock->sk)); - up_write(&cmtp_session_sem); - return err; - } -@@ -432,7 +431,11 @@ int cmtp_del_connection(struct cmtp_conndel_req *req) - - /* Stop session thread */ - atomic_inc(&session->terminate); -- wake_up_process(session->task); -+ -+ /* Ensure session->terminate is updated */ -+ smp_mb__after_atomic(); -+ -+ wake_up_interruptible(sk_sleep(session->sock->sk)); - } else - err = -ENOENT; - -diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c -index 0bec4588c3c8..1fc076420d1e 100644 ---- a/net/bluetooth/hidp/core.c -+++ b/net/bluetooth/hidp/core.c -@@ -36,6 +36,7 @@ - #define VERSION "1.2" - - static DECLARE_RWSEM(hidp_session_sem); -+static DECLARE_WAIT_QUEUE_HEAD(hidp_session_wq); - static LIST_HEAD(hidp_session_list); - - static unsigned char hidp_keycode[256] = { -@@ -1068,12 +1069,12 @@ static int hidp_session_start_sync(struct hidp_session *session) - * Wake up session thread and notify it to stop. This is asynchronous and - * returns immediately. Call this whenever a runtime error occurs and you want - * the session to stop. -- * Note: wake_up_process() performs any necessary memory-barriers for us. -+ * Note: wake_up_interruptible() performs any necessary memory-barriers for us. - */ - static void hidp_session_terminate(struct hidp_session *session) - { - atomic_inc(&session->terminate); -- wake_up_process(session->task); -+ wake_up_interruptible(&hidp_session_wq); - } - - /* -@@ -1180,7 +1181,9 @@ static void hidp_session_run(struct hidp_session *session) - struct sock *ctrl_sk = session->ctrl_sock->sk; - struct sock *intr_sk = session->intr_sock->sk; - struct sk_buff *skb; -+ DEFINE_WAIT_FUNC(wait, woken_wake_function); - -+ add_wait_queue(&hidp_session_wq, &wait); - for (;;) { - /* - * This thread can be woken up two ways: -@@ -1188,12 +1191,10 @@ static void hidp_session_run(struct hidp_session *session) - * session->terminate flag and wakes this thread up. - * - Via modifying the socket state of ctrl/intr_sock. This - * thread is woken up by ->sk_state_changed(). -- * -- * Note: set_current_state() performs any necessary -- * memory-barriers for us. - */ -- set_current_state(TASK_INTERRUPTIBLE); - -+ /* Ensure session->terminate is updated */ -+ smp_mb__before_atomic(); - if (atomic_read(&session->terminate)) - break; - -@@ -1227,11 +1228,22 @@ static void hidp_session_run(struct hidp_session *session) - hidp_process_transmit(session, &session->ctrl_transmit, - session->ctrl_sock); - -- schedule(); -+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); - } -+ remove_wait_queue(&hidp_session_wq, &wait); - - atomic_inc(&session->terminate); -- set_current_state(TASK_RUNNING); -+ -+ /* Ensure session->terminate is updated */ -+ smp_mb__after_atomic(); -+} -+ -+static int hidp_session_wake_function(wait_queue_t *wait, -+ unsigned int mode, -+ int sync, void *key) -+{ -+ wake_up_interruptible(&hidp_session_wq); -+ return false; - } - - /* -@@ -1244,7 +1256,8 @@ static void hidp_session_run(struct hidp_session *session) - static int hidp_session_thread(void *arg) - { - struct hidp_session *session = arg; -- wait_queue_t ctrl_wait, intr_wait; -+ DEFINE_WAIT_FUNC(ctrl_wait, hidp_session_wake_function); -+ DEFINE_WAIT_FUNC(intr_wait, hidp_session_wake_function); - - BT_DBG("session %p", session); - -@@ -1254,8 +1267,6 @@ static int hidp_session_thread(void *arg) - set_user_nice(current, -15); - hidp_set_timer(session); - -- init_waitqueue_entry(&ctrl_wait, current); -- init_waitqueue_entry(&intr_wait, current); - add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait); - add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait); - /* This memory barrier is paired with wq_has_sleeper(). See -diff --git a/net/dccp/proto.c b/net/dccp/proto.c -index 9fe25bf63296..b68168fcc06a 100644 ---- a/net/dccp/proto.c -+++ b/net/dccp/proto.c -@@ -24,6 +24,7 @@ - #include - - #include -+#include - #include - #include - -@@ -170,6 +171,15 @@ const char *dccp_packet_name(const int type) - - EXPORT_SYMBOL_GPL(dccp_packet_name); - -+static void dccp_sk_destruct(struct sock *sk) -+{ -+ struct dccp_sock *dp = dccp_sk(sk); -+ -+ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); -+ dp->dccps_hc_tx_ccid = NULL; -+ inet_sock_destruct(sk); -+} -+ - int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) - { - struct dccp_sock *dp = dccp_sk(sk); -@@ -179,6 +189,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) - icsk->icsk_syn_retries = sysctl_dccp_request_retries; - sk->sk_state = DCCP_CLOSED; - sk->sk_write_space = dccp_write_space; -+ sk->sk_destruct = dccp_sk_destruct; - icsk->icsk_sync_mss = dccp_sync_mss; - dp->dccps_mss_cache = 536; - dp->dccps_rate_last = jiffies; -@@ -201,10 +212,7 @@ void dccp_destroy_sock(struct sock *sk) - { - struct dccp_sock *dp = dccp_sk(sk); - -- /* -- * DCCP doesn't use sk_write_queue, just sk_send_head -- * for retransmissions -- */ -+ __skb_queue_purge(&sk->sk_write_queue); - if (sk->sk_send_head != NULL) { - kfree_skb(sk->sk_send_head); - sk->sk_send_head = NULL; -@@ -222,8 +230,7 @@ void dccp_destroy_sock(struct sock *sk) - dp->dccps_hc_rx_ackvec = NULL; - } - ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); -- ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); -- dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; -+ dp->dccps_hc_rx_ccid = NULL; - - /* clean up feature negotiation state */ - dccp_feat_list_purge(&dp->dccps_featneg); -diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c -index b2504712259f..313e3c11a15a 100644 ---- a/net/ipv4/fib_semantics.c -+++ b/net/ipv4/fib_semantics.c -@@ -1044,15 +1044,17 @@ struct fib_info *fib_create_info(struct fib_config *cfg) - fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); - if (!fi) - goto failure; -- fib_info_cnt++; - if (cfg->fc_mx) { - fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL); -- if (!fi->fib_metrics) -- goto failure; -+ if (unlikely(!fi->fib_metrics)) { -+ kfree(fi); -+ return ERR_PTR(err); -+ } - atomic_set(&fi->fib_metrics->refcnt, 1); -- } else -+ } else { - fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics; -- -+ } -+ fib_info_cnt++; - fi->fib_net = net; - fi->fib_protocol = cfg->fc_protocol; - fi->fib_scope = cfg->fc_scope; -diff --git a/net/ipv4/route.c b/net/ipv4/route.c -index c295d882c6e0..0294f7c99c85 100644 ---- a/net/ipv4/route.c -+++ b/net/ipv4/route.c -@@ -1241,7 +1241,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) - if (mtu) - return mtu; - -- mtu = dst->dev->mtu; -+ mtu = READ_ONCE(dst->dev->mtu); - - if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { - if (rt->rt_uses_gateway && mtu > 576) -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index f0dabd125c43..c4bbf704ff9c 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -3028,8 +3028,7 @@ void tcp_rearm_rto(struct sock *sk) - /* delta may not be positive if the socket is locked - * when the retrans timer fires and is rescheduled. - */ -- if (delta > 0) -- rto = delta; -+ rto = max(delta, 1); - } - inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, - TCP_RTO_MAX); -diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c -index f60e8caea767..aad8cdf15472 100644 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -892,6 +892,8 @@ add: - } - nsiblings = iter->rt6i_nsiblings; - fib6_purge_rt(iter, fn, info->nl_net); -+ if (fn->rr_ptr == iter) -+ fn->rr_ptr = NULL; - rt6_release(iter); - - if (nsiblings) { -@@ -904,6 +906,8 @@ add: - if (rt6_qualify_for_ecmp(iter)) { - *ins = iter->dst.rt6_next; - fib6_purge_rt(iter, fn, info->nl_net); -+ if (fn->rr_ptr == iter) -+ fn->rr_ptr = NULL; - rt6_release(iter); - nsiblings--; - } else { -@@ -992,7 +996,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, - /* Create subtree root node */ - sfn = node_alloc(); - if (!sfn) -- goto st_failure; -+ goto failure; - - sfn->leaf = info->nl_net->ipv6.ip6_null_entry; - atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); -@@ -1008,12 +1012,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, - - if (IS_ERR(sn)) { - /* If it is failed, discard just allocated -- root, and then (in st_failure) stale node -+ root, and then (in failure) stale node - in main tree. - */ - node_free(sfn); - err = PTR_ERR(sn); -- goto st_failure; -+ goto failure; - } - - /* Now link new subtree to main tree */ -@@ -1027,7 +1031,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, - - if (IS_ERR(sn)) { - err = PTR_ERR(sn); -- goto st_failure; -+ goto failure; - } - } - -@@ -1069,22 +1073,22 @@ out: - atomic_inc(&pn->leaf->rt6i_ref); - } - #endif -- if (!(rt->dst.flags & DST_NOCACHE)) -- dst_free(&rt->dst); -+ goto failure; - } - return err; - --#ifdef CONFIG_IPV6_SUBTREES -- /* Subtree creation failed, probably main tree node -- is orphan. If it is, shoot it. -+failure: -+ /* fn->leaf could be NULL if fn is an intermediate node and we -+ * failed to add the new route to it in both subtree creation -+ * failure and fib6_add_rt2node() failure case. -+ * In both cases, fib6_repair_tree() should be called to fix -+ * fn->leaf. - */ --st_failure: - if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) - fib6_repair_tree(info->nl_net, fn); - if (!(rt->dst.flags & DST_NOCACHE)) - dst_free(&rt->dst); - return err; --#endif - } - - /* -diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c -index 8d2f7c9b491d..4a116d766c15 100644 ---- a/net/irda/af_irda.c -+++ b/net/irda/af_irda.c -@@ -2227,7 +2227,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, - { - struct sock *sk = sock->sk; - struct irda_sock *self = irda_sk(sk); -- struct irda_device_list list; -+ struct irda_device_list list = { 0 }; - struct irda_device_info *discoveries; - struct irda_ias_set * ias_opt; /* IAS get/query params */ - struct ias_object * ias_obj; /* Object in IAS */ -diff --git a/net/key/af_key.c b/net/key/af_key.c -index 2e1050ec2cf0..94bf810ad242 100644 ---- a/net/key/af_key.c -+++ b/net/key/af_key.c -@@ -228,7 +228,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - #define BROADCAST_ONE 1 - #define BROADCAST_REGISTERED 2 - #define BROADCAST_PROMISC_ONLY 4 --static int pfkey_broadcast(struct sk_buff *skb, -+static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, - int broadcast_flags, struct sock *one_sk, - struct net *net) - { -@@ -278,7 +278,7 @@ static int pfkey_broadcast(struct sk_buff *skb, - rcu_read_unlock(); - - if (one_sk != NULL) -- err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk); -+ err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); - - kfree_skb(skb2); - kfree_skb(skb); -@@ -311,7 +311,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk) - hdr = (struct sadb_msg *) pfk->dump.skb->data; - hdr->sadb_msg_seq = 0; - hdr->sadb_msg_errno = rc; -- pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, -+ pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, - &pfk->sk, sock_net(&pfk->sk)); - pfk->dump.skb = NULL; - } -@@ -355,7 +355,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk) - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / - sizeof(uint64_t)); - -- pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); -+ pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk)); - - return 0; - } -@@ -1396,7 +1396,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_ - - xfrm_state_put(x); - -- pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net); -+ pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net); - - return 0; - } -@@ -1483,7 +1483,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c) - hdr->sadb_msg_seq = c->seq; - hdr->sadb_msg_pid = c->portid; - -- pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x)); -+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x)); - - return 0; - } -@@ -1596,7 +1596,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg - out_hdr->sadb_msg_reserved = 0; - out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; - out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; -- pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk)); -+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); - - return 0; - } -@@ -1701,8 +1701,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad - return -ENOBUFS; - } - -- pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk)); -- -+ pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, -+ sock_net(sk)); - return 0; - } - -@@ -1720,7 +1720,8 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr) - hdr->sadb_msg_errno = (uint8_t) 0; - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); - -- return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); -+ return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, -+ sock_net(sk)); - } - - static int key_notify_sa_flush(const struct km_event *c) -@@ -1741,7 +1742,7 @@ static int key_notify_sa_flush(const struct km_event *c) - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); - hdr->sadb_msg_reserved = 0; - -- pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net); -+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); - - return 0; - } -@@ -1798,7 +1799,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr) - out_hdr->sadb_msg_pid = pfk->dump.msg_portid; - - if (pfk->dump.skb) -- pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, -+ pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, - &pfk->sk, sock_net(&pfk->sk)); - pfk->dump.skb = out_skb; - -@@ -1886,7 +1887,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb - new_hdr->sadb_msg_errno = 0; - } - -- pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk)); -+ pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk)); - return 0; - } - -@@ -2219,7 +2220,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev - out_hdr->sadb_msg_errno = 0; - out_hdr->sadb_msg_seq = c->seq; - out_hdr->sadb_msg_pid = c->portid; -- pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp)); -+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp)); - return 0; - - } -@@ -2439,7 +2440,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc - out_hdr->sadb_msg_errno = 0; - out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; - out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; -- pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp)); -+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp)); - err = 0; - - out: -@@ -2695,7 +2696,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) - out_hdr->sadb_msg_pid = pfk->dump.msg_portid; - - if (pfk->dump.skb) -- pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, -+ pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, - &pfk->sk, sock_net(&pfk->sk)); - pfk->dump.skb = out_skb; - -@@ -2752,7 +2753,7 @@ static int key_notify_policy_flush(const struct km_event *c) - hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; - hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); - hdr->sadb_msg_reserved = 0; -- pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net); -+ pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); - return 0; - - } -@@ -2814,7 +2815,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb - void *ext_hdrs[SADB_EXT_MAX]; - int err; - -- pfkey_broadcast(skb_clone(skb, GFP_KERNEL), -+ pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, - BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); - - memset(ext_hdrs, 0, sizeof(ext_hdrs)); -@@ -3036,7 +3037,8 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c) - out_hdr->sadb_msg_seq = 0; - out_hdr->sadb_msg_pid = 0; - -- pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x)); -+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, -+ xs_net(x)); - return 0; - } - -@@ -3226,7 +3228,8 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct - xfrm_ctx->ctx_len); - } - -- return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); -+ return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, -+ xs_net(x)); - } - - static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, -@@ -3424,7 +3427,8 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, - n_port->sadb_x_nat_t_port_port = sport; - n_port->sadb_x_nat_t_port_reserved = 0; - -- return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); -+ return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, -+ xs_net(x)); - } - - #ifdef CONFIG_NET_KEY_MIGRATE -@@ -3616,7 +3620,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, - } - - /* broadcast migrate message to sockets */ -- pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net); -+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net); - - return 0; - -diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c -index 0915d448ba23..075b0d22f213 100644 ---- a/net/sched/act_ipt.c -+++ b/net/sched/act_ipt.c -@@ -34,6 +34,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int - { - struct xt_tgchk_param par; - struct xt_target *target; -+ struct ipt_entry e = {}; - int ret = 0; - - target = xt_request_find_target(AF_INET, t->u.user.name, -@@ -44,6 +45,7 @@ static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int - t->u.kernel.target = target; - memset(&par, 0, sizeof(par)); - par.table = table; -+ par.entryinfo = &e; - par.target = target; - par.targinfo = t->data; - par.hook_mask = hook; -diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c -index 4431e2833e45..3f2c3eed04da 100644 ---- a/net/sched/sch_sfq.c -+++ b/net/sched/sch_sfq.c -@@ -434,6 +434,7 @@ congestion_drop: - qdisc_drop(head, sch); - - slot_queue_add(slot, skb); -+ qdisc_tree_reduce_backlog(sch, 0, delta); - return NET_XMIT_CN; - } - -@@ -465,8 +466,10 @@ enqueue: - /* Return Congestion Notification only if we dropped a packet - * from this flow. - */ -- if (qlen != slot->qlen) -+ if (qlen != slot->qlen) { -+ qdisc_tree_reduce_backlog(sch, 0, dropped - qdisc_pkt_len(skb)); - return NET_XMIT_CN; -+ } - - /* As we dropped a packet, better let upper stack know this */ - qdisc_tree_reduce_backlog(sch, 1, dropped); -diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c -index 7527c168e471..e33e9bd4ed5a 100644 ---- a/net/sctp/ipv6.c -+++ b/net/sctp/ipv6.c -@@ -510,7 +510,9 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, - { - addr->sa.sa_family = AF_INET6; - addr->v6.sin6_port = port; -+ addr->v6.sin6_flowinfo = 0; - addr->v6.sin6_addr = *saddr; -+ addr->v6.sin6_scope_id = 0; - } - - /* Compare addresses exactly. -diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c -index a0c90572d0e5..f86c6555a539 100644 ---- a/net/tipc/netlink_compat.c -+++ b/net/tipc/netlink_compat.c -@@ -258,13 +258,15 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, - arg = nlmsg_new(0, GFP_KERNEL); - if (!arg) { - kfree_skb(msg->rep); -+ msg->rep = NULL; - return -ENOMEM; - } - - err = __tipc_nl_compat_dumpit(cmd, msg, arg); -- if (err) -+ if (err) { - kfree_skb(msg->rep); -- -+ msg->rep = NULL; -+ } - kfree_skb(arg); - - return err; -diff --git a/sound/core/control.c b/sound/core/control.c -index b4fe9b002512..bd01d492f46a 100644 ---- a/sound/core/control.c -+++ b/sound/core/control.c -@@ -1126,7 +1126,7 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, - mutex_lock(&ue->card->user_ctl_lock); - change = ue->tlv_data_size != size; - if (!change) -- change = memcmp(ue->tlv_data, new_data, size); -+ change = memcmp(ue->tlv_data, new_data, size) != 0; - kfree(ue->tlv_data); - ue->tlv_data = new_data; - ue->tlv_data_size = size; -diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c -index 46f7b023f69c..ac5de4365e15 100644 ---- a/sound/pci/hda/patch_conexant.c -+++ b/sound/pci/hda/patch_conexant.c -@@ -854,6 +854,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { - SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), -+ SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI), - SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004), -diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c -index 2a5b3a293cd2..b123734f9fbd 100644 ---- a/sound/soc/sh/rcar/adg.c -+++ b/sound/soc/sh/rcar/adg.c -@@ -437,7 +437,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, - struct device *dev = rsnd_priv_to_dev(priv); - struct device_node *np = dev->of_node; - u32 ckr, rbgx, rbga, rbgb; -- u32 rate, req_rate, div; -+ u32 rate, req_rate = 0, div; - uint32_t count = 0; - unsigned long req_48kHz_rate, req_441kHz_rate; - int i; -diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c -index deed48ef28b8..362446c36c9e 100644 ---- a/sound/soc/sh/rcar/core.c -+++ b/sound/soc/sh/rcar/core.c -@@ -192,19 +192,16 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod, - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io; - struct rsnd_dai *rdai; -- int i, j; -- -- for_each_rsnd_dai(rdai, priv, j) { -+ int i; - -- for (i = 0; i < RSND_MOD_MAX; i++) { -- io = &rdai->playback; -- if (mod == io->mod[i]) -- callback(mod, io); -+ for_each_rsnd_dai(rdai, priv, i) { -+ io = &rdai->playback; -+ if (mod == io->mod[mod->type]) -+ callback(mod, io); - -- io = &rdai->capture; -- if (mod == io->mod[i]) -- callback(mod, io); -- } -+ io = &rdai->capture; -+ if (mod == io->mod[mod->type]) -+ callback(mod, io); - } - } - -@@ -1019,7 +1016,7 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, - } - } - -- if (change) -+ if (change && cfg->update) - cfg->update(cfg->io, mod); - - return change; -diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c -index 68b439ed22d7..460d29cbaaa5 100644 ---- a/sound/soc/sh/rcar/src.c -+++ b/sound/soc/sh/rcar/src.c -@@ -691,13 +691,27 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) - { - rsnd_src_irq_disable_gen2(mod); - -- rsnd_mod_write(mod, SRC_CTRL, 0); -+ /* -+ * stop SRC output only -+ * see rsnd_src_quit_gen2 -+ */ -+ rsnd_mod_write(mod, SRC_CTRL, 0x01); - - rsnd_src_error_record_gen2(mod); - - return rsnd_src_stop(mod); - } - -+static int rsnd_src_quit_gen2(struct rsnd_mod *mod, -+ struct rsnd_dai_stream *io, -+ struct rsnd_priv *priv) -+{ -+ /* stop both out/in */ -+ rsnd_mod_write(mod, SRC_CTRL, 0); -+ -+ return 0; -+} -+ - static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, - struct rsnd_dai_stream *io) - { -@@ -971,7 +985,7 @@ static struct rsnd_mod_ops rsnd_src_gen2_ops = { - .probe = rsnd_src_probe_gen2, - .remove = rsnd_src_remove_gen2, - .init = rsnd_src_init_gen2, -- .quit = rsnd_src_quit, -+ .quit = rsnd_src_quit_gen2, - .start = rsnd_src_start_gen2, - .stop = rsnd_src_stop_gen2, - .hw_params = rsnd_src_hw_params, -diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c -index 1427ec21bd7e..c62a2947ac14 100644 ---- a/sound/soc/sh/rcar/ssi.c -+++ b/sound/soc/sh/rcar/ssi.c -@@ -39,6 +39,7 @@ - #define SCKP (1 << 13) /* Serial Bit Clock Polarity */ - #define SWSP (1 << 12) /* Serial WS Polarity */ - #define SDTA (1 << 10) /* Serial Data Alignment */ -+#define PDTA (1 << 9) /* Parallel Data Alignment */ - #define DEL (1 << 8) /* Serial Data Delay */ - #define CKDV(v) (v << 4) /* Serial Clock Division Ratio */ - #define TRMD (1 << 1) /* Transmit/Receive Mode Select */ -@@ -286,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 cr; - -- cr = FORCE; -+ cr = FORCE | PDTA; - - /* - * always use 32bit system word for easy clock calculation. diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.85-86.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.85-86.patch deleted file mode 100644 index a20d51922..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.85-86.patch +++ /dev/null @@ -1,393 +0,0 @@ -diff --git a/Makefile b/Makefile -index 0f3d843f42a7..1207bf6a0e7a 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 85 -+SUBLEVEL = 86 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c -index 4c46c54a3ad7..6638903f0cb9 100644 ---- a/arch/arm64/kernel/fpsimd.c -+++ b/arch/arm64/kernel/fpsimd.c -@@ -157,9 +157,11 @@ void fpsimd_thread_switch(struct task_struct *next) - - void fpsimd_flush_thread(void) - { -+ preempt_disable(); - memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state)); - fpsimd_flush_task_state(current); - set_thread_flag(TIF_FOREIGN_FPSTATE); -+ preempt_enable(); - } - - /* -diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c -index a4b466424a32..7fabf49f2aeb 100644 ---- a/arch/arm64/mm/fault.c -+++ b/arch/arm64/mm/fault.c -@@ -313,8 +313,11 @@ retry: - * signal first. We do not need to release the mmap_sem because it - * would already be released in __lock_page_or_retry in mm/filemap.c. - */ -- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) -+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { -+ if (!user_mode(regs)) -+ goto no_context; - return 0; -+ } - - /* - * Major/minor page fault accounting is only done on the initial -diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h -index de25aad07853..9016b4b70375 100644 ---- a/arch/x86/include/asm/io.h -+++ b/arch/x86/include/asm/io.h -@@ -304,13 +304,13 @@ static inline unsigned type in##bwl##_p(int port) \ - static inline void outs##bwl(int port, const void *addr, unsigned long count) \ - { \ - asm volatile("rep; outs" #bwl \ -- : "+S"(addr), "+c"(count) : "d"(port)); \ -+ : "+S"(addr), "+c"(count) : "d"(port) : "memory"); \ - } \ - \ - static inline void ins##bwl(int port, void *addr, unsigned long count) \ - { \ - asm volatile("rep; ins" #bwl \ -- : "+D"(addr), "+c"(count) : "d"(port)); \ -+ : "+D"(addr), "+c"(count) : "d"(port) : "memory"); \ - } - - BUILDIO(b, b, char) -diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c -index cc91ae832ffb..6fd7b50c5747 100644 ---- a/drivers/gpu/drm/i915/intel_uncore.c -+++ b/drivers/gpu/drm/i915/intel_uncore.c -@@ -635,7 +635,8 @@ hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv) - "enabling oneshot unclaimed register reporting. " - "Please use i915.mmio_debug=N for more information.\n"); - __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM); -- i915.mmio_debug = mmio_debug_once--; -+ i915.mmio_debug = mmio_debug_once; -+ mmio_debug_once = false; - } - } - -diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c -index f325663c27c5..4b58e8aaf5c5 100644 ---- a/drivers/i2c/busses/i2c-jz4780.c -+++ b/drivers/i2c/busses/i2c-jz4780.c -@@ -786,10 +786,6 @@ static int jz4780_i2c_probe(struct platform_device *pdev) - - jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0x0); - -- i2c->cmd = 0; -- memset(i2c->cmd_buf, 0, BUFSIZE); -- memset(i2c->data_buf, 0, BUFSIZE); -- - i2c->irq = platform_get_irq(pdev, 0); - ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0, - dev_name(&pdev->dev), i2c); -diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c -index 257a9eadd595..4ac6764f4897 100644 ---- a/drivers/net/wireless/p54/fwio.c -+++ b/drivers/net/wireless/p54/fwio.c -@@ -488,7 +488,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) - - entry += sizeof(__le16); - chan->pa_points_per_curve = 8; -- memset(chan->curve_data, 0, sizeof(*chan->curve_data)); -+ memset(chan->curve_data, 0, sizeof(chan->curve_data)); - memcpy(chan->curve_data, entry, - sizeof(struct p54_pa_curve_data_sample) * - min((u8)8, curve_data->points_per_channel)); -diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c -index 1910100638a2..00602abec0ea 100644 ---- a/drivers/scsi/isci/remote_node_context.c -+++ b/drivers/scsi/isci/remote_node_context.c -@@ -66,6 +66,9 @@ const char *rnc_state_name(enum scis_sds_remote_node_context_states state) - { - static const char * const strings[] = RNC_STATES; - -+ if (state >= ARRAY_SIZE(strings)) -+ return "UNKNOWN"; -+ - return strings[state]; - } - #undef C -diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c -index 0e6aaef9a038..c74f74ab981c 100644 ---- a/drivers/scsi/lpfc/lpfc_els.c -+++ b/drivers/scsi/lpfc/lpfc_els.c -@@ -1054,7 +1054,10 @@ stop_rr_fcf_flogi: - lpfc_sli4_unreg_all_rpis(vport); - } - } -- lpfc_issue_reg_vfi(vport); -+ -+ /* Do not register VFI if the driver aborted FLOGI */ -+ if (!lpfc_error_lost_link(irsp)) -+ lpfc_issue_reg_vfi(vport); - lpfc_nlp_put(ndlp); - goto out; - } -diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c -index 6514636431ab..8a9e139e2853 100644 ---- a/drivers/scsi/sg.c -+++ b/drivers/scsi/sg.c -@@ -153,6 +153,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ - struct sg_device *parentdp; /* owning device */ - wait_queue_head_t read_wait; /* queue read until command done */ - rwlock_t rq_list_lock; /* protect access to list in req_arr */ -+ struct mutex f_mutex; /* protect against changes in this fd */ - int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ - int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */ - Sg_scatter_hold reserve; /* buffer held for this file descriptor */ -@@ -166,6 +167,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ - unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ - char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ - char mmap_called; /* 0 -> mmap() never called on this fd */ -+ char res_in_use; /* 1 -> 'reserve' array in use */ - struct kref f_ref; - struct execute_work ew; - } Sg_fd; -@@ -209,7 +211,6 @@ static void sg_remove_sfp(struct kref *); - static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); - static Sg_request *sg_add_request(Sg_fd * sfp); - static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); --static int sg_res_in_use(Sg_fd * sfp); - static Sg_device *sg_get_dev(int dev); - static void sg_device_destroy(struct kref *kref); - -@@ -625,6 +626,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) - } - buf += SZ_SG_HEADER; - __get_user(opcode, buf); -+ mutex_lock(&sfp->f_mutex); - if (sfp->next_cmd_len > 0) { - cmd_size = sfp->next_cmd_len; - sfp->next_cmd_len = 0; /* reset so only this write() effected */ -@@ -633,6 +635,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) - if ((opcode >= 0xc0) && old_hdr.twelve_byte) - cmd_size = 12; - } -+ mutex_unlock(&sfp->f_mutex); - SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, - "sg_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size)); - /* Determine buffer size. */ -@@ -732,7 +735,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, - sg_remove_request(sfp, srp); - return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */ - } -- if (sg_res_in_use(sfp)) { -+ if (sfp->res_in_use) { - sg_remove_request(sfp, srp); - return -EBUSY; /* reserve buffer already being used */ - } -@@ -902,7 +905,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - return result; - if (val) { - sfp->low_dma = 1; -- if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { -+ if ((0 == sfp->low_dma) && !sfp->res_in_use) { - val = (int) sfp->reserve.bufflen; - sg_remove_scat(sfp, &sfp->reserve); - sg_build_reserve(sfp, val); -@@ -977,12 +980,18 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - return -EINVAL; - val = min_t(int, val, - max_sectors_bytes(sdp->device->request_queue)); -+ mutex_lock(&sfp->f_mutex); - if (val != sfp->reserve.bufflen) { -- if (sg_res_in_use(sfp) || sfp->mmap_called) -+ if (sfp->mmap_called || -+ sfp->res_in_use) { -+ mutex_unlock(&sfp->f_mutex); - return -EBUSY; -+ } -+ - sg_remove_scat(sfp, &sfp->reserve); - sg_build_reserve(sfp, val); - } -+ mutex_unlock(&sfp->f_mutex); - return 0; - case SG_GET_RESERVED_SIZE: - val = min_t(int, sfp->reserve.bufflen, -@@ -1737,13 +1746,22 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) - md = &map_data; - - if (md) { -- if (!sg_res_in_use(sfp) && dxfer_len <= rsv_schp->bufflen) -+ mutex_lock(&sfp->f_mutex); -+ if (dxfer_len <= rsv_schp->bufflen && -+ !sfp->res_in_use) { -+ sfp->res_in_use = 1; - sg_link_reserve(sfp, srp, dxfer_len); -- else { -+ } else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) { -+ mutex_unlock(&sfp->f_mutex); -+ return -EBUSY; -+ } else { - res = sg_build_indirect(req_schp, sfp, dxfer_len); -- if (res) -+ if (res) { -+ mutex_unlock(&sfp->f_mutex); - return res; -+ } - } -+ mutex_unlock(&sfp->f_mutex); - - md->pages = req_schp->pages; - md->page_order = req_schp->page_order; -@@ -2034,6 +2052,8 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) - req_schp->sglist_len = 0; - sfp->save_scat_len = 0; - srp->res_used = 0; -+ /* Called without mutex lock to avoid deadlock */ -+ sfp->res_in_use = 0; - } - - static Sg_request * -@@ -2145,6 +2165,7 @@ sg_add_sfp(Sg_device * sdp) - rwlock_init(&sfp->rq_list_lock); - - kref_init(&sfp->f_ref); -+ mutex_init(&sfp->f_mutex); - sfp->timeout = SG_DEFAULT_TIMEOUT; - sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER; - sfp->force_packid = SG_DEF_FORCE_PACK_ID; -@@ -2220,20 +2241,6 @@ sg_remove_sfp(struct kref *kref) - schedule_work(&sfp->ew.work); - } - --static int --sg_res_in_use(Sg_fd * sfp) --{ -- const Sg_request *srp; -- unsigned long iflags; -- -- read_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (srp = sfp->headrp; srp; srp = srp->nextrp) -- if (srp->res_used) -- break; -- read_unlock_irqrestore(&sfp->rq_list_lock, iflags); -- return srp ? 1 : 0; --} -- - #ifdef CONFIG_SCSI_PROC_FS - static int - sg_idr_max_id(int id, void *p, void *data) -diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c -index 9c62a6f9757a..600c67ef8a03 100644 ---- a/fs/btrfs/volumes.c -+++ b/fs/btrfs/volumes.c -@@ -108,7 +108,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { - }, - }; - --const u64 const btrfs_raid_group[BTRFS_NR_RAID_TYPES] = { -+const u64 btrfs_raid_group[BTRFS_NR_RAID_TYPES] = { - [BTRFS_RAID_RAID10] = BTRFS_BLOCK_GROUP_RAID10, - [BTRFS_RAID_RAID1] = BTRFS_BLOCK_GROUP_RAID1, - [BTRFS_RAID_DUP] = BTRFS_BLOCK_GROUP_DUP, -diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h -index 782d4e814e21..4bc4b1b13193 100644 ---- a/include/linux/lightnvm.h -+++ b/include/linux/lightnvm.h -@@ -310,6 +310,7 @@ static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev, - { - struct ppa_addr l; - -+ l.ppa = 0; - /* - * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc. - */ -diff --git a/kernel/gcov/base.c b/kernel/gcov/base.c -index 7080ae1eb6c1..f850e906564b 100644 ---- a/kernel/gcov/base.c -+++ b/kernel/gcov/base.c -@@ -98,6 +98,12 @@ void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters) - } - EXPORT_SYMBOL(__gcov_merge_icall_topn); - -+void __gcov_exit(void) -+{ -+ /* Unused. */ -+} -+EXPORT_SYMBOL(__gcov_exit); -+ - /** - * gcov_enable_events - enable event reporting through gcov_event() - * -diff --git a/kernel/gcov/gcc_4_7.c b/kernel/gcov/gcc_4_7.c -index e25e92fb44fa..46a18e72bce6 100644 ---- a/kernel/gcov/gcc_4_7.c -+++ b/kernel/gcov/gcc_4_7.c -@@ -18,7 +18,9 @@ - #include - #include "gcov.h" - --#if __GNUC__ == 5 && __GNUC_MINOR__ >= 1 -+#if (__GNUC__ >= 7) -+#define GCOV_COUNTERS 9 -+#elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) - #define GCOV_COUNTERS 10 - #elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 - #define GCOV_COUNTERS 9 -diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c -index 74177189063c..d3125c169684 100644 ---- a/sound/pci/au88x0/au88x0_core.c -+++ b/sound/pci/au88x0/au88x0_core.c -@@ -2150,8 +2150,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { - memset(stream->resources, 0, -- sizeof(unsigned char) * -- VORTEX_RESOURCE_LAST); -+ sizeof(stream->resources)); - return -EBUSY; - } - if (stream->type != VORTEX_PCM_A3D) { -@@ -2161,7 +2160,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - VORTEX_RESOURCE_MIXIN)) < 0) { - memset(stream->resources, - 0, -- sizeof(unsigned char) * VORTEX_RESOURCE_LAST); -+ sizeof(stream->resources)); - return -EBUSY; - } - } -@@ -2174,8 +2173,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - stream->resources, en, - VORTEX_RESOURCE_A3D)) < 0) { - memset(stream->resources, 0, -- sizeof(unsigned char) * -- VORTEX_RESOURCE_LAST); -+ sizeof(stream->resources)); - dev_err(vortex->card->dev, - "out of A3D sources. Sorry\n"); - return -EBUSY; -@@ -2289,8 +2287,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - VORTEX_RESOURCE_MIXOUT)) - < 0) { - memset(stream->resources, 0, -- sizeof(unsigned char) * -- VORTEX_RESOURCE_LAST); -+ sizeof(stream->resources)); - return -EBUSY; - } - if ((src[i] = -@@ -2298,8 +2295,7 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { - memset(stream->resources, 0, -- sizeof(unsigned char) * -- VORTEX_RESOURCE_LAST); -+ sizeof(stream->resources)); - return -EBUSY; - } - } diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.86-87.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.86-87.patch deleted file mode 100644 index 5292853d3..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.86-87.patch +++ /dev/null @@ -1,408 +0,0 @@ -diff --git a/Makefile b/Makefile -index 1207bf6a0e7a..f6838187b568 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 86 -+SUBLEVEL = 87 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/alpha/include/asm/types.h b/arch/alpha/include/asm/types.h -index 4cb4b6d3452c..0bc66e1d3a7e 100644 ---- a/arch/alpha/include/asm/types.h -+++ b/arch/alpha/include/asm/types.h -@@ -1,6 +1,6 @@ - #ifndef _ALPHA_TYPES_H - #define _ALPHA_TYPES_H - --#include -+#include - - #endif /* _ALPHA_TYPES_H */ -diff --git a/arch/alpha/include/uapi/asm/types.h b/arch/alpha/include/uapi/asm/types.h -index 9fd3cd459777..8d1024d7be05 100644 ---- a/arch/alpha/include/uapi/asm/types.h -+++ b/arch/alpha/include/uapi/asm/types.h -@@ -9,8 +9,18 @@ - * need to be careful to avoid a name clashes. - */ - --#ifndef __KERNEL__ -+/* -+ * This is here because we used to use l64 for alpha -+ * and we don't want to impact user mode with our change to ll64 -+ * in the kernel. -+ * -+ * However, some user programs are fine with this. They can -+ * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here. -+ */ -+#if !defined(__SANE_USERSPACE_TYPES__) && !defined(__KERNEL__) - #include -+#else -+#include - #endif - - #endif /* _UAPI_ALPHA_TYPES_H */ -diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c -index ba079e279b58..e8835d4e173c 100644 ---- a/arch/arm/kvm/mmu.c -+++ b/arch/arm/kvm/mmu.c -@@ -824,24 +824,25 @@ void stage2_unmap_vm(struct kvm *kvm) - * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all - * underlying level-2 and level-3 tables before freeing the actual level-1 table - * and setting the struct pointer to NULL. -- * -- * Note we don't need locking here as this is only called when the VM is -- * destroyed, which can only be done once. - */ - void kvm_free_stage2_pgd(struct kvm *kvm) - { -- if (kvm->arch.pgd == NULL) -- return; -+ void *pgd = NULL; -+ void *hwpgd = NULL; - - spin_lock(&kvm->mmu_lock); -- unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); -+ if (kvm->arch.pgd) { -+ unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); -+ pgd = READ_ONCE(kvm->arch.pgd); -+ hwpgd = kvm_get_hwpgd(kvm); -+ kvm->arch.pgd = NULL; -+ } - spin_unlock(&kvm->mmu_lock); - -- kvm_free_hwpgd(kvm_get_hwpgd(kvm)); -- if (KVM_PREALLOC_LEVEL > 0) -- kfree(kvm->arch.pgd); -- -- kvm->arch.pgd = NULL; -+ if (hwpgd) -+ kvm_free_hwpgd(hwpgd); -+ if (KVM_PREALLOC_LEVEL > 0 && pgd) -+ kfree(pgd); - } - - static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, -diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c -index f5e9f9310b48..b3b0004ea8ac 100644 ---- a/crypto/algif_skcipher.c -+++ b/crypto/algif_skcipher.c -@@ -86,8 +86,13 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq) - } - sgl = sreq->tsg; - n = sg_nents(sgl); -- for_each_sg(sgl, sg, n, i) -- put_page(sg_page(sg)); -+ for_each_sg(sgl, sg, n, i) { -+ struct page *page = sg_page(sg); -+ -+ /* some SGs may not have a page mapped */ -+ if (page && atomic_read(&page->_count)) -+ put_page(page); -+ } - - kfree(sreq->tsg); - } -diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c -index 025c429050c0..5d8dfe027b30 100644 ---- a/drivers/gpu/drm/ttm/ttm_page_alloc.c -+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c -@@ -612,7 +612,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, - } else { - pr_err("Failed to fill pool (%p)\n", pool); - /* If we have any pages left put them to the pool. */ -- list_for_each_entry(p, &pool->list, lru) { -+ list_for_each_entry(p, &new_pages, lru) { - ++cpages; - } - list_splice(&new_pages, &pool->list); -diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c -index 7ba795b24e75..639d1a9c8793 100644 ---- a/drivers/i2c/busses/i2c-ismt.c -+++ b/drivers/i2c/busses/i2c-ismt.c -@@ -339,8 +339,10 @@ static int ismt_process_desc(const struct ismt_desc *desc, - break; - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_I2C_BLOCK_DATA: -- memcpy(&data->block[1], dma_buffer, desc->rxbytes); -- data->block[0] = desc->rxbytes; -+ if (desc->rxbytes != dma_buffer[0] + 1) -+ return -EMSGSIZE; -+ -+ memcpy(data->block, dma_buffer, desc->rxbytes); - break; - } - return 0; -diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c -index 9e17ef27a183..6f1dbd52ec91 100644 ---- a/drivers/irqchip/irq-mips-gic.c -+++ b/drivers/irqchip/irq-mips-gic.c -@@ -915,8 +915,11 @@ static int __init gic_of_init(struct device_node *node, - gic_len = resource_size(&res); - } - -- if (mips_cm_present()) -+ if (mips_cm_present()) { - write_gcr_gic_base(gic_base | CM_GCR_GIC_BASE_GICEN_MSK); -+ /* Ensure GIC region is enabled before trying to access it */ -+ __sync(); -+ } - gic_present = true; - - __gic_init(gic_base, gic_len, cpu_vec, 0, node); -diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c -index cd4777954f87..9bee3f11898a 100644 ---- a/drivers/net/wireless/ti/wl1251/main.c -+++ b/drivers/net/wireless/ti/wl1251/main.c -@@ -1567,6 +1567,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) - - wl->state = WL1251_STATE_OFF; - mutex_init(&wl->mutex); -+ spin_lock_init(&wl->wl_lock); - - wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; - wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; -diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c -index c6a1ec110c01..22bae2b434e2 100644 ---- a/fs/ceph/addr.c -+++ b/fs/ceph/addr.c -@@ -189,7 +189,7 @@ static int ceph_releasepage(struct page *page, gfp_t g) - /* - * read a single page, without unlocking it. - */ --static int readpage_nounlock(struct file *filp, struct page *page) -+static int ceph_do_readpage(struct file *filp, struct page *page) - { - struct inode *inode = file_inode(filp); - struct ceph_inode_info *ci = ceph_inode(inode); -@@ -219,7 +219,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) - - err = ceph_readpage_from_fscache(inode, page); - if (err == 0) -- goto out; -+ return -EINPROGRESS; - - dout("readpage inode %p file %p page %p index %lu\n", - inode, filp, page, page->index); -@@ -249,8 +249,11 @@ out: - - static int ceph_readpage(struct file *filp, struct page *page) - { -- int r = readpage_nounlock(filp, page); -- unlock_page(page); -+ int r = ceph_do_readpage(filp, page); -+ if (r != -EINPROGRESS) -+ unlock_page(page); -+ else -+ r = 0; - return r; - } - -@@ -1094,7 +1097,7 @@ retry_locked: - goto retry_locked; - r = writepage_nounlock(page, NULL); - if (r < 0) -- goto fail_nosnap; -+ goto fail_unlock; - goto retry_locked; - } - -@@ -1122,11 +1125,14 @@ retry_locked: - } - - /* we need to read it. */ -- r = readpage_nounlock(file, page); -- if (r < 0) -- goto fail_nosnap; -+ r = ceph_do_readpage(file, page); -+ if (r < 0) { -+ if (r == -EINPROGRESS) -+ return -EAGAIN; -+ goto fail_unlock; -+ } - goto retry_locked; --fail_nosnap: -+fail_unlock: - unlock_page(page); - return r; - } -diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c -index a4766ded1ba7..ff1cfd7b1083 100644 ---- a/fs/ceph/cache.c -+++ b/fs/ceph/cache.c -@@ -224,13 +224,7 @@ void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci) - fscache_relinquish_cookie(cookie, 0); - } - --static void ceph_vfs_readpage_complete(struct page *page, void *data, int error) --{ -- if (!error) -- SetPageUptodate(page); --} -- --static void ceph_vfs_readpage_complete_unlock(struct page *page, void *data, int error) -+static void ceph_readpage_from_fscache_complete(struct page *page, void *data, int error) - { - if (!error) - SetPageUptodate(page); -@@ -259,7 +253,7 @@ int ceph_readpage_from_fscache(struct inode *inode, struct page *page) - return -ENOBUFS; - - ret = fscache_read_or_alloc_page(ci->fscache, page, -- ceph_vfs_readpage_complete, NULL, -+ ceph_readpage_from_fscache_complete, NULL, - GFP_KERNEL); - - switch (ret) { -@@ -288,7 +282,7 @@ int ceph_readpages_from_fscache(struct inode *inode, - return -ENOBUFS; - - ret = fscache_read_or_alloc_pages(ci->fscache, mapping, pages, nr_pages, -- ceph_vfs_readpage_complete_unlock, -+ ceph_readpage_from_fscache_complete, - NULL, mapping_gfp_mask(mapping)); - - switch (ret) { -diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c -index fa8df3fef6fc..297e05c9e2b0 100644 ---- a/fs/cifs/dir.c -+++ b/fs/cifs/dir.c -@@ -194,7 +194,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon) - int i; - - if (unlikely(direntry->d_name.len > -- tcon->fsAttrInfo.MaxPathNameComponentLength)) -+ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) - return -ENAMETOOLONG; - - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { -diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h -index b8f553b32dda..aacb15bd56fe 100644 ---- a/fs/cifs/smb2pdu.h -+++ b/fs/cifs/smb2pdu.h -@@ -82,8 +82,8 @@ - - #define NUMBER_OF_SMB2_COMMANDS 0x0013 - --/* BB FIXME - analyze following length BB */ --#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ -+/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */ -+#define MAX_SMB2_HDR_SIZE 0x00b0 - - #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) - -diff --git a/fs/eventpoll.c b/fs/eventpoll.c -index 1e009cad8d5c..1b08556776ce 100644 ---- a/fs/eventpoll.c -+++ b/fs/eventpoll.c -@@ -518,8 +518,13 @@ static void ep_remove_wait_queue(struct eppoll_entry *pwq) - wait_queue_head_t *whead; - - rcu_read_lock(); -- /* If it is cleared by POLLFREE, it should be rcu-safe */ -- whead = rcu_dereference(pwq->whead); -+ /* -+ * If it is cleared by POLLFREE, it should be rcu-safe. -+ * If we read NULL we need a barrier paired with -+ * smp_store_release() in ep_poll_callback(), otherwise -+ * we rely on whead->lock. -+ */ -+ whead = smp_load_acquire(&pwq->whead); - if (whead) - remove_wait_queue(whead, &pwq->wait); - rcu_read_unlock(); -@@ -1003,17 +1008,6 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k - struct epitem *epi = ep_item_from_wait(wait); - struct eventpoll *ep = epi->ep; - -- if ((unsigned long)key & POLLFREE) { -- ep_pwq_from_wait(wait)->whead = NULL; -- /* -- * whead = NULL above can race with ep_remove_wait_queue() -- * which can do another remove_wait_queue() after us, so we -- * can't use __remove_wait_queue(). whead->lock is held by -- * the caller. -- */ -- list_del_init(&wait->task_list); -- } -- - spin_lock_irqsave(&ep->lock, flags); - - /* -@@ -1078,6 +1072,23 @@ out_unlock: - if (pwake) - ep_poll_safewake(&ep->poll_wait); - -+ -+ if ((unsigned long)key & POLLFREE) { -+ /* -+ * If we race with ep_remove_wait_queue() it can miss -+ * ->whead = NULL and do another remove_wait_queue() after -+ * us, so we can't use __remove_wait_queue(). -+ */ -+ list_del_init(&wait->task_list); -+ /* -+ * ->whead != NULL protects us from the race with ep_free() -+ * or ep_remove(), ep_remove_wait_queue() takes whead->lock -+ * held by the caller. Once we nullify it, nothing protects -+ * ep/epi or even wait. -+ */ -+ smp_store_release(&ep_pwq_from_wait(wait)->whead, NULL); -+ } -+ - return 1; - } - -diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h -index fc824e2828f3..5d2add1a6c96 100644 ---- a/include/asm-generic/topology.h -+++ b/include/asm-generic/topology.h -@@ -48,7 +48,11 @@ - #define parent_node(node) ((void)(node),0) - #endif - #ifndef cpumask_of_node --#define cpumask_of_node(node) ((void)node, cpu_online_mask) -+ #ifdef CONFIG_NEED_MULTIPLE_NODES -+ #define cpumask_of_node(node) ((node) == 0 ? cpu_online_mask : cpu_none_mask) -+ #else -+ #define cpumask_of_node(node) ((void)node, cpu_online_mask) -+ #endif - #endif - #ifndef pcibus_to_node - #define pcibus_to_node(bus) ((void)(bus), -1) -diff --git a/kernel/cpuset.c b/kernel/cpuset.c -index 8ccd66a97c8b..2924b6faa469 100644 ---- a/kernel/cpuset.c -+++ b/kernel/cpuset.c -@@ -1910,6 +1910,7 @@ static struct cftype files[] = { - { - .name = "memory_pressure", - .read_u64 = cpuset_read_u64, -+ .private = FILE_MEMORY_PRESSURE, - }, - - { -diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c -index 77055a362041..0e01250f2072 100644 ---- a/net/xfrm/xfrm_policy.c -+++ b/net/xfrm/xfrm_policy.c -@@ -3275,9 +3275,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, - struct xfrm_state *x_new[XFRM_MAX_DEPTH]; - struct xfrm_migrate *mp; - -+ /* Stage 0 - sanity checks */ - if ((err = xfrm_migrate_check(m, num_migrate)) < 0) - goto out; - -+ if (dir >= XFRM_POLICY_MAX) { -+ err = -EINVAL; -+ goto out; -+ } -+ - /* Stage 1 - find policy */ - if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) { - err = -ENOENT; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.87-88.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.87-88.patch deleted file mode 100644 index efec1acbb..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.87-88.patch +++ /dev/null @@ -1,1154 +0,0 @@ -diff --git a/Makefile b/Makefile -index f6838187b568..788d90a0051b 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 87 -+SUBLEVEL = 88 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c -index c095455d496e..0d20cd594017 100644 ---- a/arch/arm/mm/fault.c -+++ b/arch/arm/mm/fault.c -@@ -314,8 +314,11 @@ retry: - * signal first. We do not need to release the mmap_sem because - * it would already be released in __lock_page_or_retry in - * mm/filemap.c. */ -- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) -+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { -+ if (!user_mode(regs)) -+ goto no_context; - return 0; -+ } - - /* - * Major/minor page fault accounting is only done on the -diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c -index 8d4d959a821c..8706533db57b 100644 ---- a/drivers/ata/pata_amd.c -+++ b/drivers/ata/pata_amd.c -@@ -616,6 +616,7 @@ static const struct pci_device_id amd[] = { - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 8 }, - { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 8 }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 9 }, -+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_DEV_IDE), 9 }, - - { }, - }; -diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c -index 6c15a554efbe..dc1255294628 100644 ---- a/drivers/ata/pata_cs5536.c -+++ b/drivers/ata/pata_cs5536.c -@@ -289,6 +289,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) - - static const struct pci_device_id cs5536[] = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, -+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_DEV_IDE), }, - { }, - }; - -diff --git a/drivers/base/bus.c b/drivers/base/bus.c -index 500592486e88..0346e46e2871 100644 ---- a/drivers/base/bus.c -+++ b/drivers/base/bus.c -@@ -737,7 +737,7 @@ int bus_add_driver(struct device_driver *drv) - - out_unregister: - kobject_put(&priv->kobj); -- kfree(drv->p); -+ /* drv->p is freed in driver_release() */ - drv->p = NULL; - out_put_bus: - bus_put(bus); -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index cd6b141b9825..7bb8055bd10c 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -333,6 +333,7 @@ static const struct usb_device_id blacklist_table[] = { - { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK }, - { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK }, - { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, -+ { USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK }, - - /* Additional Realtek 8821AE Bluetooth devices */ - { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, -diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c -index 00416f23b5cb..dba5c0ea0827 100644 ---- a/drivers/gpu/drm/i2c/adv7511.c -+++ b/drivers/gpu/drm/i2c/adv7511.c -@@ -36,7 +36,10 @@ struct adv7511 { - bool edid_read; - - wait_queue_head_t wq; -+ struct work_struct hpd_work; -+ - struct drm_encoder *encoder; -+ struct drm_connector connector; - - bool embedded_sync; - enum adv7511_sync_polarity vsync_polarity; -@@ -48,6 +51,10 @@ struct adv7511 { - struct gpio_desc *gpio_pd; - }; - -+static const int edid_i2c_addr = 0x7e; -+static const int packet_i2c_addr = 0x70; -+static const int cec_i2c_addr = 0x78; -+ - static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder) - { - return to_encoder_slave(encoder)->slave_priv; -@@ -362,12 +369,19 @@ static void adv7511_power_on(struct adv7511 *adv7511) - { - adv7511->current_edid_segment = -1; - -- regmap_write(adv7511->regmap, ADV7511_REG_INT(0), -- ADV7511_INT0_EDID_READY); -- regmap_write(adv7511->regmap, ADV7511_REG_INT(1), -- ADV7511_INT1_DDC_ERROR); - regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, - ADV7511_POWER_POWER_DOWN, 0); -+ if (adv7511->i2c_main->irq) { -+ /* -+ * Documentation says the INT_ENABLE registers are reset in -+ * POWER_DOWN mode. My 7511w preserved the bits, however. -+ * Still, let's be safe and stick to the documentation. -+ */ -+ regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), -+ ADV7511_INT0_EDID_READY); -+ regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), -+ ADV7511_INT1_DDC_ERROR); -+ } - - /* - * Per spec it is allowed to pulse the HDP signal to indicate that the -@@ -422,7 +436,27 @@ static bool adv7511_hpd(struct adv7511 *adv7511) - return false; - } - --static int adv7511_irq_process(struct adv7511 *adv7511) -+static void adv7511_hpd_work(struct work_struct *work) -+{ -+ struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work); -+ enum drm_connector_status status; -+ unsigned int val; -+ int ret; -+ ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val); -+ if (ret < 0) -+ status = connector_status_disconnected; -+ else if (val & ADV7511_STATUS_HPD) -+ status = connector_status_connected; -+ else -+ status = connector_status_disconnected; -+ -+ if (adv7511->connector.status != status) { -+ adv7511->connector.status = status; -+ drm_kms_helper_hotplug_event(adv7511->connector.dev); -+ } -+} -+ -+static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd) - { - unsigned int irq0, irq1; - int ret; -@@ -438,8 +472,8 @@ static int adv7511_irq_process(struct adv7511 *adv7511) - regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0); - regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1); - -- if (irq0 & ADV7511_INT0_HDP && adv7511->encoder) -- drm_helper_hpd_irq_event(adv7511->encoder->dev); -+ if (process_hpd && irq0 & ADV7511_INT0_HDP && adv7511->encoder) -+ schedule_work(&adv7511->hpd_work); - - if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) { - adv7511->edid_read = true; -@@ -456,7 +490,7 @@ static irqreturn_t adv7511_irq_handler(int irq, void *devid) - struct adv7511 *adv7511 = devid; - int ret; - -- ret = adv7511_irq_process(adv7511); -+ ret = adv7511_irq_process(adv7511, true); - return ret < 0 ? IRQ_NONE : IRQ_HANDLED; - } - -@@ -473,7 +507,7 @@ static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout) - adv7511->edid_read, msecs_to_jiffies(timeout)); - } else { - for (; timeout > 0; timeout -= 25) { -- ret = adv7511_irq_process(adv7511); -+ ret = adv7511_irq_process(adv7511, false); - if (ret < 0) - break; - -@@ -567,13 +601,18 @@ static int adv7511_get_modes(struct drm_encoder *encoder, - - /* Reading the EDID only works if the device is powered */ - if (!adv7511->powered) { -- regmap_write(adv7511->regmap, ADV7511_REG_INT(0), -- ADV7511_INT0_EDID_READY); -- regmap_write(adv7511->regmap, ADV7511_REG_INT(1), -- ADV7511_INT1_DDC_ERROR); - regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER, - ADV7511_POWER_POWER_DOWN, 0); -+ if (adv7511->i2c_main->irq) { -+ regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), -+ ADV7511_INT0_EDID_READY); -+ regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), -+ ADV7511_INT1_DDC_ERROR); -+ } - adv7511->current_edid_segment = -1; -+ /* Reset the EDID_I2C_ADDR register as it might be cleared */ -+ regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, -+ edid_i2c_addr); - } - - edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511); -@@ -849,10 +888,6 @@ static int adv7511_parse_dt(struct device_node *np, - return 0; - } - --static const int edid_i2c_addr = 0x7e; --static const int packet_i2c_addr = 0x70; --static const int cec_i2c_addr = 0x78; -- - static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) - { - struct adv7511_link_config link_config; -@@ -913,6 +948,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) - if (!adv7511->i2c_edid) - return -ENOMEM; - -+ INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work); -+ - if (i2c->irq) { - init_waitqueue_head(&adv7511->wq); - -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c -index d671dcfaff3c..4896474da320 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c -@@ -180,6 +180,10 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device, - } - } - -+#ifdef __BIG_ENDIAN -+ pci->msi = false; -+#endif -+ - pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi); - if (pci->msi && func->msi_rearm) { - pci->msi = pci_enable_msi(pci->pdev) == 0; -diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c -index d57a2f75dccf..32c6a40a408f 100644 ---- a/drivers/hwtracing/intel_th/pci.c -+++ b/drivers/hwtracing/intel_th/pci.c -@@ -72,6 +72,16 @@ static const struct pci_device_id intel_th_pci_id_table[] = { - PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), - .driver_data = (kernel_ulong_t)0, - }, -+ { -+ /* Cannon Lake H */ -+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326), -+ .driver_data = (kernel_ulong_t)0, -+ }, -+ { -+ /* Cannon Lake LP */ -+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), -+ .driver_data = (kernel_ulong_t)0, -+ }, - { 0 }, - }; - -diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c -index ce6ff9b301bb..7e2dc5e56632 100644 ---- a/drivers/input/mouse/trackpoint.c -+++ b/drivers/input/mouse/trackpoint.c -@@ -381,8 +381,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) - return 0; - - if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { -- psmouse_warn(psmouse, "failed to get extended button data\n"); -- button_info = 0; -+ psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n"); -+ button_info = 0x33; - } - - psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); -diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c -index 531de256d58d..05de75360fa4 100644 ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -1607,6 +1607,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) - goto err_wmi_detach; - } - -+ /* If firmware indicates Full Rx Reorder support it must be used in a -+ * slightly different manner. Let HTT code know. -+ */ -+ ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER, -+ ar->wmi.svc_map)); -+ - status = ath10k_htt_rx_alloc(&ar->htt); - if (status) { - ath10k_err(ar, "failed to alloc htt rx: %d\n", status); -@@ -1669,12 +1675,6 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) - goto err_hif_stop; - } - -- /* If firmware indicates Full Rx Reorder support it must be used in a -- * slightly different manner. Let HTT code know. -- */ -- ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER, -- ar->wmi.svc_map)); -- - status = ath10k_htt_rx_ring_refill(ar); - if (status) { - ath10k_err(ar, "failed to refill htt rx ring: %d\n", status); -diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c -index c3331d6201c3..9a8982f581c5 100644 ---- a/drivers/net/wireless/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/mwifiex/cfg80211.c -@@ -3740,7 +3740,7 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) - if (adapter->config_bands & BAND_A) - n_channels_a = mwifiex_band_5ghz.n_channels; - -- adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); -+ adapter->num_in_chan_stats = n_channels_bg + n_channels_a; - adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * - adapter->num_in_chan_stats); - -diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c -index c20017ced566..fb98f42cb5e7 100644 ---- a/drivers/net/wireless/mwifiex/scan.c -+++ b/drivers/net/wireless/mwifiex/scan.c -@@ -2170,6 +2170,12 @@ mwifiex_update_chan_statistics(struct mwifiex_private *priv, - sizeof(struct mwifiex_chan_stats); - - for (i = 0 ; i < num_chan; i++) { -+ if (adapter->survey_idx >= adapter->num_in_chan_stats) { -+ mwifiex_dbg(adapter, WARN, -+ "FW reported too many channel results (max %d)\n", -+ adapter->num_in_chan_stats); -+ return; -+ } - chan_stats.chan_num = fw_chan_stats->chan_num; - chan_stats.bandcfg = fw_chan_stats->bandcfg; - chan_stats.flags = fw_chan_stats->flags; -diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c -index a52230377e2c..c48b7e8ee0d6 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/pci.c -+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c -@@ -2269,7 +2269,7 @@ int rtl_pci_probe(struct pci_dev *pdev, - /* find adapter */ - if (!_rtl_pci_find_adapter(pdev, hw)) { - err = -ENODEV; -- goto fail3; -+ goto fail2; - } - - /* Init IO handler */ -@@ -2339,10 +2339,10 @@ fail3: - pci_set_drvdata(pdev, NULL); - rtl_deinit_core(hw); - -+fail2: - if (rtlpriv->io.pci_mem_start != 0) - pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); - --fail2: - pci_release_regions(pdev); - complete(&rtlpriv->firmware_loading_complete); - -diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c -index 8a9e139e2853..71325972e503 100644 ---- a/drivers/scsi/sg.c -+++ b/drivers/scsi/sg.c -@@ -1254,6 +1254,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) - unsigned long req_sz, len, sa; - Sg_scatter_hold *rsv_schp; - int k, length; -+ int ret = 0; - - if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) - return -ENXIO; -@@ -1264,8 +1265,11 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) - if (vma->vm_pgoff) - return -EINVAL; /* want no offset */ - rsv_schp = &sfp->reserve; -- if (req_sz > rsv_schp->bufflen) -- return -ENOMEM; /* cannot map more than reserved buffer */ -+ mutex_lock(&sfp->f_mutex); -+ if (req_sz > rsv_schp->bufflen) { -+ ret = -ENOMEM; /* cannot map more than reserved buffer */ -+ goto out; -+ } - - sa = vma->vm_start; - length = 1 << (PAGE_SHIFT + rsv_schp->page_order); -@@ -1279,7 +1283,9 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) - vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP; - vma->vm_private_data = sfp; - vma->vm_ops = &sg_mmap_vm_ops; -- return 0; -+out: -+ mutex_unlock(&sfp->f_mutex); -+ return ret; - } - - static void -@@ -1751,9 +1757,12 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) - !sfp->res_in_use) { - sfp->res_in_use = 1; - sg_link_reserve(sfp, srp, dxfer_len); -- } else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) { -+ } else if (hp->flags & SG_FLAG_MMAP_IO) { -+ res = -EBUSY; /* sfp->res_in_use == 1 */ -+ if (dxfer_len > rsv_schp->bufflen) -+ res = -ENOMEM; - mutex_unlock(&sfp->f_mutex); -- return -EBUSY; -+ return res; - } else { - res = sg_build_indirect(req_schp, sfp, dxfer_len); - if (res) { -diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c -index 60871f3022b1..12a3893b98fd 100644 ---- a/drivers/staging/rts5208/rtsx_scsi.c -+++ b/drivers/staging/rts5208/rtsx_scsi.c -@@ -414,7 +414,7 @@ void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, - sense->ascq = ascq; - if (sns_key_info0 != 0) { - sense->sns_key_info[0] = SKSV | sns_key_info0; -- sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8; -+ sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 4; - sense->sns_key_info[2] = sns_key_info1 & 0x0f; - } - } -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index 54d2d6b604c0..873ba02d59e6 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -519,6 +519,8 @@ static void async_completed(struct urb *urb) - if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && - as->status != -ENOENT) - cancel_bulk_urbs(ps, as->bulk_addr); -+ -+ wake_up(&ps->wait); - spin_unlock(&ps->lock); - - if (signr) { -@@ -526,8 +528,6 @@ static void async_completed(struct urb *urb) - put_pid(pid); - put_cred(cred); - } -- -- wake_up(&ps->wait); - } - - static void destroy_async(struct usb_dev_state *ps, struct list_head *list) -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 574da2b4529c..82806e311202 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -57,8 +57,9 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Microsoft LifeCam-VX700 v2.0 */ - { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, - -- /* Logitech HD Pro Webcams C920 and C930e */ -+ /* Logitech HD Pro Webcams C920, C920-C and C930e */ - { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, -+ { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, - { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, - - /* Logitech ConferenceCam CC3000e */ -@@ -217,6 +218,9 @@ static const struct usb_device_id usb_quirk_list[] = { - { USB_DEVICE(0x1a0a, 0x0200), .driver_info = - USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, - -+ /* Corsair Strafe RGB */ -+ { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, -+ - /* Acer C120 LED Projector */ - { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, - -diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c -index 03b9a372636f..1fc6f478a02c 100644 ---- a/drivers/usb/host/pci-quirks.c -+++ b/drivers/usb/host/pci-quirks.c -@@ -133,29 +133,30 @@ static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo) - pinfo->sb_type.gen = AMD_CHIPSET_SB700; - else if (rev >= 0x40 && rev <= 0x4f) - pinfo->sb_type.gen = AMD_CHIPSET_SB800; -- } -- pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, -- 0x145c, NULL); -- if (pinfo->smbus_dev) { -- pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN; - } else { - pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL); - -- if (!pinfo->smbus_dev) { -- pinfo->sb_type.gen = NOT_AMD_CHIPSET; -- return 0; -+ if (pinfo->smbus_dev) { -+ rev = pinfo->smbus_dev->revision; -+ if (rev >= 0x11 && rev <= 0x14) -+ pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2; -+ else if (rev >= 0x15 && rev <= 0x18) -+ pinfo->sb_type.gen = AMD_CHIPSET_BOLTON; -+ else if (rev >= 0x39 && rev <= 0x3a) -+ pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE; -+ } else { -+ pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, -+ 0x145c, NULL); -+ if (pinfo->smbus_dev) { -+ rev = pinfo->smbus_dev->revision; -+ pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN; -+ } else { -+ pinfo->sb_type.gen = NOT_AMD_CHIPSET; -+ return 0; -+ } - } -- -- rev = pinfo->smbus_dev->revision; -- if (rev >= 0x11 && rev <= 0x14) -- pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2; -- else if (rev >= 0x15 && rev <= 0x18) -- pinfo->sb_type.gen = AMD_CHIPSET_BOLTON; -- else if (rev >= 0x39 && rev <= 0x3a) -- pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE; - } -- - pinfo->sb_type.rev = rev; - return 1; - } -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index fe123153b1a5..2a9944326210 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -2023,6 +2023,7 @@ static const struct usb_device_id option_ids[] = { - { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, - { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, - { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) }, /* D-Link DWM-158 */ -+ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) }, /* D-Link DWM-157 C1 */ - { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ - .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff), /* D-Link DWM-222 */ -diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c -index 5d34a062ca4f..3bd2233737ac 100644 ---- a/fs/btrfs/super.c -+++ b/fs/btrfs/super.c -@@ -1727,6 +1727,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) - goto restore; - } - -+ btrfs_qgroup_rescan_resume(fs_info); -+ - if (!fs_info->uuid_root) { - btrfs_info(fs_info, "creating UUID tree"); - ret = btrfs_create_uuid_tree(fs_info); -diff --git a/fs/dlm/user.c b/fs/dlm/user.c -index 173b3873a4f4..e40c440a4555 100644 ---- a/fs/dlm/user.c -+++ b/fs/dlm/user.c -@@ -355,6 +355,10 @@ static int dlm_device_register(struct dlm_ls *ls, char *name) - error = misc_register(&ls->ls_device); - if (error) { - kfree(ls->ls_device.name); -+ /* this has to be set to NULL -+ * to avoid a double-free in dlm_device_deregister -+ */ -+ ls->ls_device.name = NULL; - } - fail: - return error; -diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h -index 9dea85f7f918..578350fd96e1 100644 ---- a/fs/nfs/internal.h -+++ b/fs/nfs/internal.h -@@ -243,7 +243,6 @@ int nfs_iocounter_wait(struct nfs_io_counter *c); - extern const struct nfs_pageio_ops nfs_pgio_rw_ops; - struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *); - void nfs_pgio_header_free(struct nfs_pgio_header *); --void nfs_pgio_data_destroy(struct nfs_pgio_header *); - int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *); - int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr, - struct rpc_cred *cred, const struct nfs_rpc_ops *rpc_ops, -diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c -index 452a011ba0d8..8ebfdd00044b 100644 ---- a/fs/nfs/pagelist.c -+++ b/fs/nfs/pagelist.c -@@ -528,16 +528,6 @@ struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *ops) - } - EXPORT_SYMBOL_GPL(nfs_pgio_header_alloc); - --/* -- * nfs_pgio_header_free - Free a read or write header -- * @hdr: The header to free -- */ --void nfs_pgio_header_free(struct nfs_pgio_header *hdr) --{ -- hdr->rw_ops->rw_free_header(hdr); --} --EXPORT_SYMBOL_GPL(nfs_pgio_header_free); -- - /** - * nfs_pgio_data_destroy - make @hdr suitable for reuse - * -@@ -546,14 +536,24 @@ EXPORT_SYMBOL_GPL(nfs_pgio_header_free); - * - * @hdr: A header that has had nfs_generic_pgio called - */ --void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr) -+static void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr) - { - if (hdr->args.context) - put_nfs_open_context(hdr->args.context); - if (hdr->page_array.pagevec != hdr->page_array.page_array) - kfree(hdr->page_array.pagevec); - } --EXPORT_SYMBOL_GPL(nfs_pgio_data_destroy); -+ -+/* -+ * nfs_pgio_header_free - Free a read or write header -+ * @hdr: The header to free -+ */ -+void nfs_pgio_header_free(struct nfs_pgio_header *hdr) -+{ -+ nfs_pgio_data_destroy(hdr); -+ hdr->rw_ops->rw_free_header(hdr); -+} -+EXPORT_SYMBOL_GPL(nfs_pgio_header_free); - - /** - * nfs_pgio_rpcsetup - Set up arguments for a pageio call -@@ -671,7 +671,6 @@ static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, - u32 midx; - - set_bit(NFS_IOHDR_REDO, &hdr->flags); -- nfs_pgio_data_destroy(hdr); - hdr->completion_ops->completion(hdr); - /* TODO: Make sure it's right to clean up all mirrors here - * and not just hdr->pgio_mirror_idx */ -@@ -689,7 +688,6 @@ static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, - static void nfs_pgio_release(void *calldata) - { - struct nfs_pgio_header *hdr = calldata; -- nfs_pgio_data_destroy(hdr); - hdr->completion_ops->completion(hdr); - } - -diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c -index 3cae0726c1b1..7af7bedd7c02 100644 ---- a/fs/nfs/pnfs.c -+++ b/fs/nfs/pnfs.c -@@ -1943,7 +1943,6 @@ pnfs_write_through_mds(struct nfs_pageio_descriptor *desc, - nfs_pageio_reset_write_mds(desc); - mirror->pg_recoalesce = 1; - } -- nfs_pgio_data_destroy(hdr); - hdr->release(hdr); - } - -@@ -2059,7 +2058,6 @@ pnfs_read_through_mds(struct nfs_pageio_descriptor *desc, - nfs_pageio_reset_read_mds(desc); - mirror->pg_recoalesce = 1; - } -- nfs_pgio_data_destroy(hdr); - hdr->release(hdr); - } - -diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h -index ec0e239a0fa9..201aae0b2662 100644 ---- a/fs/xfs/xfs_linux.h -+++ b/fs/xfs/xfs_linux.h -@@ -369,7 +369,14 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y) - #endif /* DEBUG */ - - #ifdef CONFIG_XFS_RT --#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) -+ -+/* -+ * make sure we ignore the inode flag if the filesystem doesn't have a -+ * configured realtime device. -+ */ -+#define XFS_IS_REALTIME_INODE(ip) \ -+ (((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) && \ -+ (ip)->i_mount->m_rtdev_targp) - #else - #define XFS_IS_REALTIME_INODE(ip) (0) - #endif -diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h -index 37f05cb1dfd6..1af616138d1d 100644 ---- a/include/linux/pci_ids.h -+++ b/include/linux/pci_ids.h -@@ -573,6 +573,7 @@ - #define PCI_DEVICE_ID_AMD_CS5536_EHC 0x2095 - #define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096 - #define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 -+#define PCI_DEVICE_ID_AMD_CS5536_DEV_IDE 0x2092 - #define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A - #define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 - #define PCI_DEVICE_ID_AMD_LX_AES 0x2082 -diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h -index 262d5c95dfc8..217abe56e711 100644 ---- a/include/linux/workqueue.h -+++ b/include/linux/workqueue.h -@@ -311,7 +311,7 @@ enum { - - __WQ_DRAINING = 1 << 16, /* internal: workqueue is draining */ - __WQ_ORDERED = 1 << 17, /* internal: workqueue is ordered */ -- __WQ_ORDERED_EXPLICIT = 1 << 18, /* internal: alloc_ordered_workqueue() */ -+ __WQ_ORDERED_EXPLICIT = 1 << 19, /* internal: alloc_ordered_workqueue() */ - - WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */ - WQ_MAX_UNBOUND_PER_CPU = 4, /* 4 * #cpus for unbound wq */ -diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c -index 8ef1919d63b2..d580b7d6ee6d 100644 ---- a/kernel/locking/locktorture.c -+++ b/kernel/locking/locktorture.c -@@ -776,6 +776,8 @@ static void lock_torture_cleanup(void) - else - lock_torture_print_module_parms(cxt.cur_ops, - "End of test: SUCCESS"); -+ kfree(cxt.lwsa); -+ kfree(cxt.lrsa); - torture_cleanup_end(); - } - -@@ -917,6 +919,8 @@ static int __init lock_torture_init(void) - GFP_KERNEL); - if (reader_tasks == NULL) { - VERBOSE_TOROUT_ERRSTRING("reader_tasks: Out of memory"); -+ kfree(writer_tasks); -+ writer_tasks = NULL; - firsterr = -ENOMEM; - goto unwind; - } -diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c -index 66e8b6ee19a5..357bcd34cf1f 100644 ---- a/net/bluetooth/l2cap_core.c -+++ b/net/bluetooth/l2cap_core.c -@@ -57,7 +57,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, - u8 code, u8 ident, u16 dlen, void *data); - static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, - void *data); --static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); -+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); - static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); - - static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, -@@ -1462,7 +1462,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) - - set_bit(CONF_REQ_SENT, &chan->conf_state); - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), buf); -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); - chan->num_conf_req++; - } - -@@ -2966,12 +2966,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, - return len; - } - --static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) -+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) - { - struct l2cap_conf_opt *opt = *ptr; - - BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); - -+ if (size < L2CAP_CONF_OPT_SIZE + len) -+ return; -+ - opt->type = type; - opt->len = len; - -@@ -2996,7 +2999,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) - *ptr += L2CAP_CONF_OPT_SIZE + len; - } - --static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) -+static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) - { - struct l2cap_conf_efs efs; - -@@ -3024,7 +3027,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) - } - - l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), -- (unsigned long) &efs); -+ (unsigned long) &efs, size); - } - - static void l2cap_ack_timeout(struct work_struct *work) -@@ -3170,11 +3173,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan) - chan->ack_win = chan->tx_win; - } - --static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) -+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) - { - struct l2cap_conf_req *req = data; - struct l2cap_conf_rfc rfc = { .mode = chan->mode }; - void *ptr = req->data; -+ void *endptr = data + data_size; - u16 size; - - BT_DBG("chan %p", chan); -@@ -3199,7 +3203,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) - - done: - if (chan->imtu != L2CAP_DEFAULT_MTU) -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); - - switch (chan->mode) { - case L2CAP_MODE_BASIC: -@@ -3218,7 +3222,7 @@ done: - rfc.max_pdu_size = 0; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), -- (unsigned long) &rfc); -+ (unsigned long) &rfc, endptr - ptr); - break; - - case L2CAP_MODE_ERTM: -@@ -3238,21 +3242,21 @@ done: - L2CAP_DEFAULT_TX_WINDOW); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), -- (unsigned long) &rfc); -+ (unsigned long) &rfc, endptr - ptr); - - if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) -- l2cap_add_opt_efs(&ptr, chan); -+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr); - - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, -- chan->tx_win); -+ chan->tx_win, endptr - ptr); - - if (chan->conn->feat_mask & L2CAP_FEAT_FCS) - if (chan->fcs == L2CAP_FCS_NONE || - test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { - chan->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, -- chan->fcs); -+ chan->fcs, endptr - ptr); - } - break; - -@@ -3270,17 +3274,17 @@ done: - rfc.max_pdu_size = cpu_to_le16(size); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), -- (unsigned long) &rfc); -+ (unsigned long) &rfc, endptr - ptr); - - if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) -- l2cap_add_opt_efs(&ptr, chan); -+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr); - - if (chan->conn->feat_mask & L2CAP_FEAT_FCS) - if (chan->fcs == L2CAP_FCS_NONE || - test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { - chan->fcs = L2CAP_FCS_NONE; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, -- chan->fcs); -+ chan->fcs, endptr - ptr); - } - break; - } -@@ -3291,10 +3295,11 @@ done: - return ptr - data; - } - --static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) -+static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) - { - struct l2cap_conf_rsp *rsp = data; - void *ptr = rsp->data; -+ void *endptr = data + data_size; - void *req = chan->conf_req; - int len = chan->conf_len; - int type, hint, olen; -@@ -3396,7 +3401,7 @@ done: - return -ECONNREFUSED; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), -- (unsigned long) &rfc); -+ (unsigned long) &rfc, endptr - ptr); - } - - if (result == L2CAP_CONF_SUCCESS) { -@@ -3409,7 +3414,7 @@ done: - chan->omtu = mtu; - set_bit(CONF_MTU_DONE, &chan->conf_state); - } -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); - - if (remote_efs) { - if (chan->local_stype != L2CAP_SERV_NOTRAFIC && -@@ -3423,7 +3428,7 @@ done: - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, - sizeof(efs), -- (unsigned long) &efs); -+ (unsigned long) &efs, endptr - ptr); - } else { - /* Send PENDING Conf Rsp */ - result = L2CAP_CONF_PENDING; -@@ -3456,7 +3461,7 @@ done: - set_bit(CONF_MODE_DONE, &chan->conf_state); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, -- sizeof(rfc), (unsigned long) &rfc); -+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr); - - if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { - chan->remote_id = efs.id; -@@ -3470,7 +3475,7 @@ done: - le32_to_cpu(efs.sdu_itime); - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, - sizeof(efs), -- (unsigned long) &efs); -+ (unsigned long) &efs, endptr - ptr); - } - break; - -@@ -3484,7 +3489,7 @@ done: - set_bit(CONF_MODE_DONE, &chan->conf_state); - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), -- (unsigned long) &rfc); -+ (unsigned long) &rfc, endptr - ptr); - - break; - -@@ -3506,10 +3511,11 @@ done: - } - - static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, -- void *data, u16 *result) -+ void *data, size_t size, u16 *result) - { - struct l2cap_conf_req *req = data; - void *ptr = req->data; -+ void *endptr = data + size; - int type, olen; - unsigned long val; - struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; -@@ -3527,13 +3533,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, - chan->imtu = L2CAP_DEFAULT_MIN_MTU; - } else - chan->imtu = val; -- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); -+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); - break; - - case L2CAP_CONF_FLUSH_TO: - chan->flush_to = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, -- 2, chan->flush_to); -+ 2, chan->flush_to, endptr - ptr); - break; - - case L2CAP_CONF_RFC: -@@ -3547,13 +3553,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, - chan->fcs = 0; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, -- sizeof(rfc), (unsigned long) &rfc); -+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr); - break; - - case L2CAP_CONF_EWS: - chan->ack_win = min_t(u16, val, chan->ack_win); - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, -- chan->tx_win); -+ chan->tx_win, endptr - ptr); - break; - - case L2CAP_CONF_EFS: -@@ -3566,7 +3572,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, - return -ECONNREFUSED; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), -- (unsigned long) &efs); -+ (unsigned long) &efs, endptr - ptr); - break; - - case L2CAP_CONF_FCS: -@@ -3671,7 +3677,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) - return; - - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), buf); -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); - chan->num_conf_req++; - } - -@@ -3879,7 +3885,7 @@ sendresp: - u8 buf[128]; - set_bit(CONF_REQ_SENT, &chan->conf_state); - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), buf); -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); - chan->num_conf_req++; - } - -@@ -3957,7 +3963,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, - break; - - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, req), req); -+ l2cap_build_conf_req(chan, req, sizeof(req)), req); - chan->num_conf_req++; - break; - -@@ -4069,7 +4075,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, - } - - /* Complete config. */ -- len = l2cap_parse_conf_req(chan, rsp); -+ len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); - if (len < 0) { - l2cap_send_disconn_req(chan, ECONNRESET); - goto unlock; -@@ -4103,7 +4109,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, - if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { - u8 buf[64]; - l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), buf); -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); - chan->num_conf_req++; - } - -@@ -4163,7 +4169,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, - char buf[64]; - - len = l2cap_parse_conf_rsp(chan, rsp->data, len, -- buf, &result); -+ buf, sizeof(buf), &result); - if (len < 0) { - l2cap_send_disconn_req(chan, ECONNRESET); - goto done; -@@ -4193,7 +4199,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, - /* throw out any old stored conf requests */ - result = L2CAP_CONF_SUCCESS; - len = l2cap_parse_conf_rsp(chan, rsp->data, len, -- req, &result); -+ req, sizeof(req), &result); - if (len < 0) { - l2cap_send_disconn_req(chan, ECONNRESET); - goto done; -@@ -4770,7 +4776,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, - set_bit(CONF_REQ_SENT, &chan->conf_state); - l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), - L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), buf); -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); - chan->num_conf_req++; - } - } -@@ -7442,7 +7448,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) - set_bit(CONF_REQ_SENT, &chan->conf_state); - l2cap_send_cmd(conn, l2cap_get_ident(conn), - L2CAP_CONF_REQ, -- l2cap_build_conf_req(chan, buf), -+ l2cap_build_conf_req(chan, buf, sizeof(buf)), - buf); - chan->num_conf_req++; - } -diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c -index ffc67fd80c23..58e59cd3c95c 100644 ---- a/sound/isa/msnd/msnd_midi.c -+++ b/sound/isa/msnd/msnd_midi.c -@@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv) - unsigned long flags; - struct snd_msndmidi *mpu = mpuv; - void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; -+ u16 head, tail, size; - - spin_lock_irqsave(&mpu->input_lock, flags); -- while (readw(mpu->dev->MIDQ + JQS_wTail) != -- readw(mpu->dev->MIDQ + JQS_wHead)) { -- u16 wTmp, val; -- val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); -- -- if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, -- &mpu->mode)) -- snd_rawmidi_receive(mpu->substream_input, -- (unsigned char *)&val, 1); -- -- wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; -- if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) -- writew(0, mpu->dev->MIDQ + JQS_wHead); -- else -- writew(wTmp, mpu->dev->MIDQ + JQS_wHead); -+ head = readw(mpu->dev->MIDQ + JQS_wHead); -+ tail = readw(mpu->dev->MIDQ + JQS_wTail); -+ size = readw(mpu->dev->MIDQ + JQS_wSize); -+ if (head > size || tail > size) -+ goto out; -+ while (head != tail) { -+ unsigned char val = readw(pwMIDQData + 2 * head); -+ -+ if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) -+ snd_rawmidi_receive(mpu->substream_input, &val, 1); -+ if (++head > size) -+ head = 0; -+ writew(head, mpu->dev->MIDQ + JQS_wHead); - } -+ out: - spin_unlock_irqrestore(&mpu->input_lock, flags); - } - EXPORT_SYMBOL(snd_msndmidi_input_read); -diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c -index 4c072666115d..a31ea6c22d19 100644 ---- a/sound/isa/msnd/msnd_pinnacle.c -+++ b/sound/isa/msnd/msnd_pinnacle.c -@@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) - { - struct snd_msnd *chip = dev_id; - void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; -+ u16 head, tail, size; - - /* Send ack to DSP */ - /* inb(chip->io + HP_RXL); */ - - /* Evaluate queued DSP messages */ -- while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { -- u16 wTmp; -- -- snd_msnd_eval_dsp_msg(chip, -- readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); -- -- wTmp = readw(chip->DSPQ + JQS_wHead) + 1; -- if (wTmp > readw(chip->DSPQ + JQS_wSize)) -- writew(0, chip->DSPQ + JQS_wHead); -- else -- writew(wTmp, chip->DSPQ + JQS_wHead); -+ head = readw(chip->DSPQ + JQS_wHead); -+ tail = readw(chip->DSPQ + JQS_wTail); -+ size = readw(chip->DSPQ + JQS_wSize); -+ if (head > size || tail > size) -+ goto out; -+ while (head != tail) { -+ snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head)); -+ if (++head > size) -+ head = 0; -+ writew(head, chip->DSPQ + JQS_wHead); - } -+ out: - /* Send ack to DSP */ - inb(chip->io + HP_RXL); - return IRQ_HANDLED; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.88-89.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.88-89.patch deleted file mode 100644 index 28665fb4f..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.88-89.patch +++ /dev/null @@ -1,2770 +0,0 @@ -diff --git a/Makefile b/Makefile -index 788d90a0051b..7e4c46b375b3 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 88 -+SUBLEVEL = 89 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S -index 2efb0625331d..db1eee5fe502 100644 ---- a/arch/arc/kernel/entry.S -+++ b/arch/arc/kernel/entry.S -@@ -104,6 +104,12 @@ ENTRY(EV_MachineCheck) - lr r0, [efa] - mov r1, sp - -+ ; hardware auto-disables MMU, re-enable it to allow kernel vaddr -+ ; access for say stack unwinding of modules for crash dumps -+ lr r3, [ARC_REG_PID] -+ or r3, r3, MMU_ENABLE -+ sr r3, [ARC_REG_PID] -+ - lsr r3, r2, 8 - bmsk r3, r3, 7 - brne r3, ECR_C_MCHK_DUP_TLB, 1f -diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c -index daf2bf52b984..97e9582dcf99 100644 ---- a/arch/arc/mm/tlb.c -+++ b/arch/arc/mm/tlb.c -@@ -885,9 +885,6 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, - - local_irq_save(flags); - -- /* re-enable the MMU */ -- write_aux_reg(ARC_REG_PID, MMU_ENABLE | read_aux_reg(ARC_REG_PID)); -- - /* loop thru all sets of TLB */ - for (set = 0; set < mmu->sets; set++) { - -diff --git a/arch/mips/math-emu/dp_fmax.c b/arch/mips/math-emu/dp_fmax.c -index fd71b8daaaf2..5bec64f2884e 100644 ---- a/arch/mips/math-emu/dp_fmax.c -+++ b/arch/mips/math-emu/dp_fmax.c -@@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -80,9 +92,7 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y) - return ys ? x : y; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754dp_zero(1); -+ return ieee754dp_zero(xs & ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; -@@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y) - else if (xs < ys) - return x; - -- /* Compare exponent */ -- if (xe > ye) -- return x; -- else if (xe < ye) -- return y; -+ /* Signs of inputs are equal, let's compare exponents */ -+ if (xs == 0) { -+ /* Inputs are both positive */ -+ if (xe > ye) -+ return x; -+ else if (xe < ye) -+ return y; -+ } else { -+ /* Inputs are both negative */ -+ if (xe > ye) -+ return y; -+ else if (xe < ye) -+ return x; -+ } - -- /* Compare mantissa */ -+ /* Signs and exponents of inputs are equal, let's compare mantissas */ -+ if (xs == 0) { -+ /* Inputs are both positive, with equal signs and exponents */ -+ if (xm <= ym) -+ return y; -+ return x; -+ } -+ /* Inputs are both negative, with equal signs and exponents */ - if (xm <= ym) -- return y; -- return x; -+ return x; -+ return y; - } - - union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) -@@ -147,14 +173,26 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -164,6 +202,9 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) - /* - * Infinity and zero handling - */ -+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -+ return ieee754dp_inf(xs & ys); -+ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): -@@ -171,7 +212,6 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - -- case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): -@@ -180,9 +220,7 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) - return y; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754dp_zero(1); -+ return ieee754dp_zero(xs & ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; -@@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y) - return y; - - /* Compare mantissa */ -- if (xm <= ym) -+ if (xm < ym) - return y; -- return x; -+ else if (xm > ym) -+ return x; -+ else if (xs == 0) -+ return x; -+ return y; - } -diff --git a/arch/mips/math-emu/dp_fmin.c b/arch/mips/math-emu/dp_fmin.c -index c1072b0dfb95..a287b23818d8 100644 ---- a/arch/mips/math-emu/dp_fmin.c -+++ b/arch/mips/math-emu/dp_fmin.c -@@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -80,9 +92,7 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y) - return ys ? y : x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754dp_zero(1); -+ return ieee754dp_zero(xs | ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; -@@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y) - else if (xs < ys) - return y; - -- /* Compare exponent */ -- if (xe > ye) -- return y; -- else if (xe < ye) -- return x; -+ /* Signs of inputs are the same, let's compare exponents */ -+ if (xs == 0) { -+ /* Inputs are both positive */ -+ if (xe > ye) -+ return y; -+ else if (xe < ye) -+ return x; -+ } else { -+ /* Inputs are both negative */ -+ if (xe > ye) -+ return x; -+ else if (xe < ye) -+ return y; -+ } - -- /* Compare mantissa */ -+ /* Signs and exponents of inputs are equal, let's compare mantissas */ -+ if (xs == 0) { -+ /* Inputs are both positive, with equal signs and exponents */ -+ if (xm <= ym) -+ return x; -+ return y; -+ } -+ /* Inputs are both negative, with equal signs and exponents */ - if (xm <= ym) -- return x; -- return y; -+ return y; -+ return x; - } - - union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y) -@@ -147,14 +173,26 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -164,25 +202,25 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y) - /* - * Infinity and zero handling - */ -+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -+ return ieee754dp_inf(xs | ys); -+ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): -- return x; -+ return y; - -- case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): -- return y; -+ return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754dp_zero(1); -+ return ieee754dp_zero(xs | ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; -@@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y) - return x; - - /* Compare mantissa */ -- if (xm <= ym) -+ if (xm < ym) -+ return x; -+ else if (xm > ym) -+ return y; -+ else if (xs == 1) - return x; - return y; - } -diff --git a/arch/mips/math-emu/sp_fmax.c b/arch/mips/math-emu/sp_fmax.c -index 4d000844e48e..74a5a00d2f22 100644 ---- a/arch/mips/math-emu/sp_fmax.c -+++ b/arch/mips/math-emu/sp_fmax.c -@@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -80,9 +92,7 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y) - return ys ? x : y; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754sp_zero(1); -+ return ieee754sp_zero(xs & ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; -@@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y) - else if (xs < ys) - return x; - -- /* Compare exponent */ -- if (xe > ye) -- return x; -- else if (xe < ye) -- return y; -+ /* Signs of inputs are equal, let's compare exponents */ -+ if (xs == 0) { -+ /* Inputs are both positive */ -+ if (xe > ye) -+ return x; -+ else if (xe < ye) -+ return y; -+ } else { -+ /* Inputs are both negative */ -+ if (xe > ye) -+ return y; -+ else if (xe < ye) -+ return x; -+ } - -- /* Compare mantissa */ -+ /* Signs and exponents of inputs are equal, let's compare mantissas */ -+ if (xs == 0) { -+ /* Inputs are both positive, with equal signs and exponents */ -+ if (xm <= ym) -+ return y; -+ return x; -+ } -+ /* Inputs are both negative, with equal signs and exponents */ - if (xm <= ym) -- return y; -- return x; -+ return x; -+ return y; - } - - union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) -@@ -147,14 +173,26 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -164,6 +202,9 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) - /* - * Infinity and zero handling - */ -+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -+ return ieee754sp_inf(xs & ys); -+ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): -@@ -171,7 +212,6 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - -- case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): -@@ -180,9 +220,7 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) - return y; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754sp_zero(1); -+ return ieee754sp_zero(xs & ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; -@@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y) - return y; - - /* Compare mantissa */ -- if (xm <= ym) -+ if (xm < ym) - return y; -- return x; -+ else if (xm > ym) -+ return x; -+ else if (xs == 0) -+ return x; -+ return y; - } -diff --git a/arch/mips/math-emu/sp_fmin.c b/arch/mips/math-emu/sp_fmin.c -index 4eb1bb9e9dec..c51385f46b09 100644 ---- a/arch/mips/math-emu/sp_fmin.c -+++ b/arch/mips/math-emu/sp_fmin.c -@@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -80,9 +92,7 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y) - return ys ? y : x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754sp_zero(1); -+ return ieee754sp_zero(xs | ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; -@@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y) - else if (xs < ys) - return y; - -- /* Compare exponent */ -- if (xe > ye) -- return y; -- else if (xe < ye) -- return x; -+ /* Signs of inputs are the same, let's compare exponents */ -+ if (xs == 0) { -+ /* Inputs are both positive */ -+ if (xe > ye) -+ return y; -+ else if (xe < ye) -+ return x; -+ } else { -+ /* Inputs are both negative */ -+ if (xe > ye) -+ return x; -+ else if (xe < ye) -+ return y; -+ } - -- /* Compare mantissa */ -+ /* Signs and exponents of inputs are equal, let's compare mantissas */ -+ if (xs == 0) { -+ /* Inputs are both positive, with equal signs and exponents */ -+ if (xm <= ym) -+ return x; -+ return y; -+ } -+ /* Inputs are both negative, with equal signs and exponents */ - if (xm <= ym) -- return x; -- return y; -+ return y; -+ return x; - } - - union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y) -@@ -147,14 +173,26 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y) - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x); - -- /* numbers are preferred to NaNs */ -+ /* -+ * Quiet NaN handling -+ */ -+ -+ /* -+ * The case of both inputs quiet NaNs -+ */ -+ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): -+ return x; -+ -+ /* -+ * The cases of exactly one input quiet NaN (numbers -+ * are here preferred as returned values to NaNs) -+ */ - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return x; - -- case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): -@@ -164,25 +202,25 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y) - /* - * Infinity and zero handling - */ -+ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): -+ return ieee754sp_inf(xs | ys); -+ - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): -- return x; -+ return y; - -- case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): -- return y; -+ return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): -- if (xs == ys) -- return x; -- return ieee754sp_zero(1); -+ return ieee754sp_zero(xs | ys); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; -@@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y) - return x; - - /* Compare mantissa */ -- if (xm <= ym) -+ if (xm < ym) -+ return x; -+ else if (xm > ym) -+ return y; -+ else if (xs == 1) - return x; - return y; - } -diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c -index 91e5c1758b5c..64e016abb2a5 100644 ---- a/arch/powerpc/kernel/align.c -+++ b/arch/powerpc/kernel/align.c -@@ -236,6 +236,28 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) - - #define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) - -+#define __get_user_or_set_dar(_regs, _dest, _addr) \ -+ ({ \ -+ int rc = 0; \ -+ typeof(_addr) __addr = (_addr); \ -+ if (__get_user_inatomic(_dest, __addr)) { \ -+ _regs->dar = (unsigned long)__addr; \ -+ rc = -EFAULT; \ -+ } \ -+ rc; \ -+ }) -+ -+#define __put_user_or_set_dar(_regs, _src, _addr) \ -+ ({ \ -+ int rc = 0; \ -+ typeof(_addr) __addr = (_addr); \ -+ if (__put_user_inatomic(_src, __addr)) { \ -+ _regs->dar = (unsigned long)__addr; \ -+ rc = -EFAULT; \ -+ } \ -+ rc; \ -+ }) -+ - static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, - unsigned int reg, unsigned int nb, - unsigned int flags, unsigned int instr, -@@ -264,9 +286,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, - } else { - unsigned long pc = regs->nip ^ (swiz & 4); - -- if (__get_user_inatomic(instr, -- (unsigned int __user *)pc)) -+ if (__get_user_or_set_dar(regs, instr, -+ (unsigned int __user *)pc)) - return -EFAULT; -+ - if (swiz == 0 && (flags & SW)) - instr = cpu_to_le32(instr); - nb = (instr >> 11) & 0x1f; -@@ -310,31 +333,31 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, - ((nb0 + 3) / 4) * sizeof(unsigned long)); - - for (i = 0; i < nb; ++i, ++p) -- if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz), -- SWIZ_PTR(p))) -+ if (__get_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz), -+ SWIZ_PTR(p))) - return -EFAULT; - if (nb0 > 0) { - rptr = ®s->gpr[0]; - addr += nb; - for (i = 0; i < nb0; ++i, ++p) -- if (__get_user_inatomic(REG_BYTE(rptr, -- i ^ bswiz), -- SWIZ_PTR(p))) -+ if (__get_user_or_set_dar(regs, -+ REG_BYTE(rptr, i ^ bswiz), -+ SWIZ_PTR(p))) - return -EFAULT; - } - - } else { - for (i = 0; i < nb; ++i, ++p) -- if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz), -- SWIZ_PTR(p))) -+ if (__put_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz), -+ SWIZ_PTR(p))) - return -EFAULT; - if (nb0 > 0) { - rptr = ®s->gpr[0]; - addr += nb; - for (i = 0; i < nb0; ++i, ++p) -- if (__put_user_inatomic(REG_BYTE(rptr, -- i ^ bswiz), -- SWIZ_PTR(p))) -+ if (__put_user_or_set_dar(regs, -+ REG_BYTE(rptr, i ^ bswiz), -+ SWIZ_PTR(p))) - return -EFAULT; - } - } -@@ -346,29 +369,32 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, - * Only POWER6 has these instructions, and it does true little-endian, - * so we don't need the address swizzling. - */ --static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg, -- unsigned int flags) -+static int emulate_fp_pair(struct pt_regs *regs, unsigned char __user *addr, -+ unsigned int reg, unsigned int flags) - { - char *ptr0 = (char *) ¤t->thread.TS_FPR(reg); - char *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1); -- int i, ret, sw = 0; -+ int i, sw = 0; - - if (reg & 1) - return 0; /* invalid form: FRS/FRT must be even */ - if (flags & SW) - sw = 7; -- ret = 0; -+ - for (i = 0; i < 8; ++i) { - if (!(flags & ST)) { -- ret |= __get_user(ptr0[i^sw], addr + i); -- ret |= __get_user(ptr1[i^sw], addr + i + 8); -+ if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i)) -+ return -EFAULT; -+ if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8)) -+ return -EFAULT; - } else { -- ret |= __put_user(ptr0[i^sw], addr + i); -- ret |= __put_user(ptr1[i^sw], addr + i + 8); -+ if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i)) -+ return -EFAULT; -+ if (__put_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8)) -+ return -EFAULT; - } - } -- if (ret) -- return -EFAULT; -+ - return 1; /* exception handled and fixed up */ - } - -@@ -378,24 +404,27 @@ static int emulate_lq_stq(struct pt_regs *regs, unsigned char __user *addr, - { - char *ptr0 = (char *)®s->gpr[reg]; - char *ptr1 = (char *)®s->gpr[reg+1]; -- int i, ret, sw = 0; -+ int i, sw = 0; - - if (reg & 1) - return 0; /* invalid form: GPR must be even */ - if (flags & SW) - sw = 7; -- ret = 0; -+ - for (i = 0; i < 8; ++i) { - if (!(flags & ST)) { -- ret |= __get_user(ptr0[i^sw], addr + i); -- ret |= __get_user(ptr1[i^sw], addr + i + 8); -+ if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i)) -+ return -EFAULT; -+ if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8)) -+ return -EFAULT; - } else { -- ret |= __put_user(ptr0[i^sw], addr + i); -- ret |= __put_user(ptr1[i^sw], addr + i + 8); -+ if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i)) -+ return -EFAULT; -+ if (__put_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8)) -+ return -EFAULT; - } - } -- if (ret) -- return -EFAULT; -+ - return 1; /* exception handled and fixed up */ - } - #endif /* CONFIG_PPC64 */ -@@ -688,9 +717,14 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, - for (j = 0; j < length; j += elsize) { - for (i = 0; i < elsize; ++i) { - if (flags & ST) -- ret |= __put_user(ptr[i^sw], addr + i); -+ ret = __put_user_or_set_dar(regs, ptr[i^sw], -+ addr + i); - else -- ret |= __get_user(ptr[i^sw], addr + i); -+ ret = __get_user_or_set_dar(regs, ptr[i^sw], -+ addr + i); -+ -+ if (ret) -+ return ret; - } - ptr += elsize; - #ifdef __LITTLE_ENDIAN__ -@@ -740,7 +774,7 @@ int fix_alignment(struct pt_regs *regs) - unsigned int dsisr; - unsigned char __user *addr; - unsigned long p, swiz; -- int ret, i; -+ int i; - union data { - u64 ll; - double dd; -@@ -923,7 +957,7 @@ int fix_alignment(struct pt_regs *regs) - if (flags & F) { - /* Special case for 16-byte FP loads and stores */ - PPC_WARN_ALIGNMENT(fp_pair, regs); -- return emulate_fp_pair(addr, reg, flags); -+ return emulate_fp_pair(regs, addr, reg, flags); - } else { - #ifdef CONFIG_PPC64 - /* Special case for 16-byte loads and stores */ -@@ -953,15 +987,12 @@ int fix_alignment(struct pt_regs *regs) - } - - data.ll = 0; -- ret = 0; - p = (unsigned long)addr; - - for (i = 0; i < nb; i++) -- ret |= __get_user_inatomic(data.v[start + i], -- SWIZ_PTR(p++)); -- -- if (unlikely(ret)) -- return -EFAULT; -+ if (__get_user_or_set_dar(regs, data.v[start + i], -+ SWIZ_PTR(p++))) -+ return -EFAULT; - - } else if (flags & F) { - data.ll = current->thread.TS_FPR(reg); -@@ -1031,15 +1062,13 @@ int fix_alignment(struct pt_regs *regs) - break; - } - -- ret = 0; - p = (unsigned long)addr; - - for (i = 0; i < nb; i++) -- ret |= __put_user_inatomic(data.v[start + i], -- SWIZ_PTR(p++)); -+ if (__put_user_or_set_dar(regs, data.v[start + i], -+ SWIZ_PTR(p++))) -+ return -EFAULT; - -- if (unlikely(ret)) -- return -EFAULT; - } else if (flags & F) - current->thread.TS_FPR(reg) = data.ll; - else -diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h -index bcd3d6199464..bb16a58cf7e4 100644 ---- a/arch/x86/include/asm/elf.h -+++ b/arch/x86/include/asm/elf.h -@@ -204,6 +204,7 @@ void set_personality_ia32(bool); - - #define ELF_CORE_COPY_REGS(pr_reg, regs) \ - do { \ -+ unsigned long base; \ - unsigned v; \ - (pr_reg)[0] = (regs)->r15; \ - (pr_reg)[1] = (regs)->r14; \ -@@ -226,8 +227,8 @@ do { \ - (pr_reg)[18] = (regs)->flags; \ - (pr_reg)[19] = (regs)->sp; \ - (pr_reg)[20] = (regs)->ss; \ -- (pr_reg)[21] = current->thread.fs; \ -- (pr_reg)[22] = current->thread.gs; \ -+ rdmsrl(MSR_FS_BASE, base); (pr_reg)[21] = base; \ -+ rdmsrl(MSR_KERNEL_GS_BASE, base); (pr_reg)[22] = base; \ - asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v; \ - asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v; \ - asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v; \ -diff --git a/block/blk-core.c b/block/blk-core.c -index ef083e7a37c5..119658534dfd 100644 ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -233,7 +233,7 @@ EXPORT_SYMBOL(blk_start_queue_async); - **/ - void blk_start_queue(struct request_queue *q) - { -- WARN_ON(!irqs_disabled()); -+ WARN_ON(!in_interrupt() && !irqs_disabled()); - - queue_flag_clear(QUEUE_FLAG_STOPPED, q); - __blk_run_queue(q); -diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c -index b3b0004ea8ac..d12782dc9683 100644 ---- a/crypto/algif_skcipher.c -+++ b/crypto/algif_skcipher.c -@@ -143,8 +143,10 @@ static int skcipher_alloc_sgl(struct sock *sk) - sg_init_table(sgl->sg, MAX_SGL_ENTS + 1); - sgl->cur = 0; - -- if (sg) -+ if (sg) { - sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg); -+ sg_unmark_end(sg + (MAX_SGL_ENTS - 1)); -+ } - - list_add_tail(&sgl->list, &ctx->tsgl); - } -diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c -index 586f9168ffa4..47d1e834f3f4 100644 ---- a/drivers/block/skd_main.c -+++ b/drivers/block/skd_main.c -@@ -2214,6 +2214,9 @@ static void skd_send_fitmsg(struct skd_device *skdev, - */ - qcmd |= FIT_QCMD_MSGSIZE_64; - -+ /* Make sure skd_msg_buf is written before the doorbell is triggered. */ -+ smp_wmb(); -+ - SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND); - - } -@@ -2260,6 +2263,9 @@ static void skd_send_special_fitmsg(struct skd_device *skdev, - qcmd = skspcl->mb_dma_address; - qcmd |= FIT_QCMD_QID_NORMAL + FIT_QCMD_MSGSIZE_128; - -+ /* Make sure skd_msg_buf is written before the doorbell is triggered. */ -+ smp_wmb(); -+ - SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND); - } - -@@ -4679,15 +4685,16 @@ static void skd_free_disk(struct skd_device *skdev) - { - struct gendisk *disk = skdev->disk; - -- if (disk != NULL) { -- struct request_queue *q = disk->queue; -+ if (disk && (disk->flags & GENHD_FL_UP)) -+ del_gendisk(disk); - -- if (disk->flags & GENHD_FL_UP) -- del_gendisk(disk); -- if (q) -- blk_cleanup_queue(q); -- put_disk(disk); -+ if (skdev->queue) { -+ blk_cleanup_queue(skdev->queue); -+ skdev->queue = NULL; -+ disk->queue = NULL; - } -+ -+ put_disk(disk); - skdev->disk = NULL; - } - -diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h -index 5be14ad29d46..dbf09836ff30 100644 ---- a/drivers/input/serio/i8042-x86ia64io.h -+++ b/drivers/input/serio/i8042-x86ia64io.h -@@ -904,6 +904,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "P34"), - }, - }, -+ { -+ /* Gigabyte P57 - Elantech touchpad */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "P57"), -+ }, -+ }, - { - /* Schenker XMG C504 - Elantech touchpad */ - .matches = { -diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h -index c3ea03c9a1a8..02619cabda8b 100644 ---- a/drivers/md/bcache/bcache.h -+++ b/drivers/md/bcache/bcache.h -@@ -333,6 +333,7 @@ struct cached_dev { - /* Limit number of writeback bios in flight */ - struct semaphore in_flight; - struct task_struct *writeback_thread; -+ struct workqueue_struct *writeback_write_wq; - - struct keybuf writeback_keys; - -diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c -index 2410df1c2a05..6c4c7caea693 100644 ---- a/drivers/md/bcache/request.c -+++ b/drivers/md/bcache/request.c -@@ -196,12 +196,12 @@ static void bch_data_insert_start(struct closure *cl) - struct data_insert_op *op = container_of(cl, struct data_insert_op, cl); - struct bio *bio = op->bio, *n; - -- if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) -- wake_up_gc(op->c); -- - if (op->bypass) - return bch_data_invalidate(cl); - -+ if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) -+ wake_up_gc(op->c); -+ - /* - * Journal writes are marked REQ_FLUSH; if the original write was a - * flush, it'll wait on the journal write. -diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c -index 7b5880b8874c..c5ceea9222ff 100644 ---- a/drivers/md/bcache/super.c -+++ b/drivers/md/bcache/super.c -@@ -1023,7 +1023,7 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c) - } - - if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) { -- bch_sectors_dirty_init(dc); -+ bch_sectors_dirty_init(&dc->disk); - atomic_set(&dc->has_dirty, 1); - atomic_inc(&dc->count); - bch_writeback_queue(dc); -@@ -1056,6 +1056,8 @@ static void cached_dev_free(struct closure *cl) - cancel_delayed_work_sync(&dc->writeback_rate_update); - if (!IS_ERR_OR_NULL(dc->writeback_thread)) - kthread_stop(dc->writeback_thread); -+ if (dc->writeback_write_wq) -+ destroy_workqueue(dc->writeback_write_wq); - - mutex_lock(&bch_register_lock); - -@@ -1227,6 +1229,7 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u) - goto err; - - bcache_device_attach(d, c, u - c->uuids); -+ bch_sectors_dirty_init(d); - bch_flash_dev_request_init(d); - add_disk(d->disk); - -@@ -1959,6 +1962,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, - else - err = "device busy"; - mutex_unlock(&bch_register_lock); -+ if (!IS_ERR(bdev)) -+ bdput(bdev); - if (attr == &ksysfs_register_quiet) - goto out; - } -diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c -index b3ff57d61dde..4fbb5532f24c 100644 ---- a/drivers/md/bcache/sysfs.c -+++ b/drivers/md/bcache/sysfs.c -@@ -191,7 +191,7 @@ STORE(__cached_dev) - { - struct cached_dev *dc = container_of(kobj, struct cached_dev, - disk.kobj); -- unsigned v = size; -+ ssize_t v = size; - struct cache_set *c; - struct kobj_uevent_env *env; - -@@ -226,7 +226,7 @@ STORE(__cached_dev) - bch_cached_dev_run(dc); - - if (attr == &sysfs_cache_mode) { -- ssize_t v = bch_read_string_list(buf, bch_cache_modes + 1); -+ v = bch_read_string_list(buf, bch_cache_modes + 1); - - if (v < 0) - return v; -diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c -index db3ae4c2b223..6c18e3ec3e48 100644 ---- a/drivers/md/bcache/util.c -+++ b/drivers/md/bcache/util.c -@@ -73,24 +73,44 @@ STRTO_H(strtouint, unsigned int) - STRTO_H(strtoll, long long) - STRTO_H(strtoull, unsigned long long) - -+/** -+ * bch_hprint() - formats @v to human readable string for sysfs. -+ * -+ * @v - signed 64 bit integer -+ * @buf - the (at least 8 byte) buffer to format the result into. -+ * -+ * Returns the number of bytes used by format. -+ */ - ssize_t bch_hprint(char *buf, int64_t v) - { - static const char units[] = "?kMGTPEZY"; -- char dec[4] = ""; -- int u, t = 0; -- -- for (u = 0; v >= 1024 || v <= -1024; u++) { -- t = v & ~(~0 << 10); -- v >>= 10; -- } -- -- if (!u) -- return sprintf(buf, "%llu", v); -- -- if (v < 100 && v > -100) -- snprintf(dec, sizeof(dec), ".%i", t / 100); -- -- return sprintf(buf, "%lli%s%c", v, dec, units[u]); -+ int u = 0, t; -+ -+ uint64_t q; -+ -+ if (v < 0) -+ q = -v; -+ else -+ q = v; -+ -+ /* For as long as the number is more than 3 digits, but at least -+ * once, shift right / divide by 1024. Keep the remainder for -+ * a digit after the decimal point. -+ */ -+ do { -+ u++; -+ -+ t = q & ~(~0 << 10); -+ q >>= 10; -+ } while (q >= 1000); -+ -+ if (v < 0) -+ /* '-', up to 3 digits, '.', 1 digit, 1 character, null; -+ * yields 8 bytes. -+ */ -+ return sprintf(buf, "-%llu.%i%c", q, t * 10 / 1024, units[u]); -+ else -+ return sprintf(buf, "%llu.%i%c", q, t * 10 / 1024, units[u]); - } - - ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[], -diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c -index b9346cd9cda1..bbb1dc9e1639 100644 ---- a/drivers/md/bcache/writeback.c -+++ b/drivers/md/bcache/writeback.c -@@ -21,7 +21,8 @@ - static void __update_writeback_rate(struct cached_dev *dc) - { - struct cache_set *c = dc->disk.c; -- uint64_t cache_sectors = c->nbuckets * c->sb.bucket_size; -+ uint64_t cache_sectors = c->nbuckets * c->sb.bucket_size - -+ bcache_flash_devs_sectors_dirty(c); - uint64_t cache_dirty_target = - div_u64(cache_sectors * dc->writeback_percent, 100); - -@@ -190,7 +191,7 @@ static void write_dirty(struct closure *cl) - - closure_bio_submit(&io->bio, cl); - -- continue_at(cl, write_dirty_finish, system_wq); -+ continue_at(cl, write_dirty_finish, io->dc->writeback_write_wq); - } - - static void read_dirty_endio(struct bio *bio) -@@ -210,7 +211,7 @@ static void read_dirty_submit(struct closure *cl) - - closure_bio_submit(&io->bio, cl); - -- continue_at(cl, write_dirty, system_wq); -+ continue_at(cl, write_dirty, io->dc->writeback_write_wq); - } - - static void read_dirty(struct cached_dev *dc) -@@ -488,17 +489,17 @@ static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b, - return MAP_CONTINUE; - } - --void bch_sectors_dirty_init(struct cached_dev *dc) -+void bch_sectors_dirty_init(struct bcache_device *d) - { - struct sectors_dirty_init op; - - bch_btree_op_init(&op.op, -1); -- op.inode = dc->disk.id; -+ op.inode = d->id; - -- bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0), -+ bch_btree_map_keys(&op.op, d->c, &KEY(op.inode, 0, 0), - sectors_dirty_init_fn, 0); - -- dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk); -+ d->sectors_dirty_last = bcache_dev_sectors_dirty(d); - } - - void bch_cached_dev_writeback_init(struct cached_dev *dc) -@@ -522,6 +523,11 @@ void bch_cached_dev_writeback_init(struct cached_dev *dc) - - int bch_cached_dev_writeback_start(struct cached_dev *dc) - { -+ dc->writeback_write_wq = alloc_workqueue("bcache_writeback_wq", -+ WQ_MEM_RECLAIM, 0); -+ if (!dc->writeback_write_wq) -+ return -ENOMEM; -+ - dc->writeback_thread = kthread_create(bch_writeback_thread, dc, - "bcache_writeback"); - if (IS_ERR(dc->writeback_thread)) -diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h -index 073a042aed24..daec4fd782ea 100644 ---- a/drivers/md/bcache/writeback.h -+++ b/drivers/md/bcache/writeback.h -@@ -14,6 +14,25 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d) - return ret; - } - -+static inline uint64_t bcache_flash_devs_sectors_dirty(struct cache_set *c) -+{ -+ uint64_t i, ret = 0; -+ -+ mutex_lock(&bch_register_lock); -+ -+ for (i = 0; i < c->nr_uuids; i++) { -+ struct bcache_device *d = c->devices[i]; -+ -+ if (!d || !UUID_FLASH_ONLY(&c->uuids[i])) -+ continue; -+ ret += bcache_dev_sectors_dirty(d); -+ } -+ -+ mutex_unlock(&bch_register_lock); -+ -+ return ret; -+} -+ - static inline unsigned offset_to_stripe(struct bcache_device *d, - uint64_t offset) - { -@@ -85,7 +104,7 @@ static inline void bch_writeback_add(struct cached_dev *dc) - - void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int); - --void bch_sectors_dirty_init(struct cached_dev *dc); -+void bch_sectors_dirty_init(struct bcache_device *); - void bch_cached_dev_writeback_init(struct cached_dev *); - int bch_cached_dev_writeback_start(struct cached_dev *); - -diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c -index 4f22e919787a..7a50728b9389 100644 ---- a/drivers/md/bitmap.c -+++ b/drivers/md/bitmap.c -@@ -1960,6 +1960,11 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks, - long pages; - struct bitmap_page *new_bp; - -+ if (bitmap->storage.file && !init) { -+ pr_info("md: cannot resize file-based bitmap\n"); -+ return -EINVAL; -+ } -+ - if (chunksize == 0) { - /* If there is enough space, leave the chunk size unchanged, - * else increase by factor of two until there is enough space. -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 8f60520c8392..5eac08ffc697 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -5822,6 +5822,8 @@ static void raid5_do_work(struct work_struct *work) - - spin_unlock_irq(&conf->device_lock); - -+ r5l_flush_stripe_to_raid(conf->log); -+ - async_tx_issue_pending_all(); - blk_finish_plug(&plug); - -diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c -index 3e59b288b8a8..618e4e2b4207 100644 ---- a/drivers/media/usb/uvc/uvc_ctrl.c -+++ b/drivers/media/usb/uvc/uvc_ctrl.c -@@ -2001,6 +2001,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, - goto done; - } - -+ /* Validate the user-provided bit-size and offset */ -+ if (mapping->size > 32 || -+ mapping->offset + mapping->size > ctrl->info.size * 8) { -+ ret = -EINVAL; -+ goto done; -+ } -+ - list_for_each_entry(map, &ctrl->info.mappings, list) { - if (mapping->id == map->id) { - uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " -diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -index 109f687d1cbd..4379b949bb93 100644 ---- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c -@@ -773,7 +773,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u - copy_to_user(&up->u, &kp->u, sizeof(kp->u)) || - put_user(kp->pending, &up->pending) || - put_user(kp->sequence, &up->sequence) || -- compat_put_timespec(&kp->timestamp, &up->timestamp) || -+ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) || -+ put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) || - put_user(kp->id, &up->id) || - copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32))) - return -EFAULT; -diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c -index 4cd2a7d0124f..7923bfdc9b30 100644 ---- a/drivers/net/ethernet/freescale/gianfar.c -+++ b/drivers/net/ethernet/freescale/gianfar.c -@@ -3676,7 +3676,7 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) - u32 tempval1 = gfar_read(®s->maccfg1); - u32 tempval = gfar_read(®s->maccfg2); - u32 ecntrl = gfar_read(®s->ecntrl); -- u32 tx_flow_oldval = (tempval & MACCFG1_TX_FLOW); -+ u32 tx_flow_oldval = (tempval1 & MACCFG1_TX_FLOW); - - if (phydev->duplex != priv->oldduplex) { - if (!(phydev->duplex)) -diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c -index 829be21f97b2..be258d90de9e 100644 ---- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c -+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c -@@ -724,7 +724,7 @@ static void ql_build_coredump_seg_header( - seg_hdr->cookie = MPI_COREDUMP_COOKIE; - seg_hdr->segNum = seg_number; - seg_hdr->segSize = seg_size; -- memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); -+ strncpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); - } - - /* -diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c -index 7d223e9080ef..77dddee2753a 100644 ---- a/drivers/pci/hotplug/shpchp_hpc.c -+++ b/drivers/pci/hotplug/shpchp_hpc.c -@@ -1062,6 +1062,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) - if (rc) { - ctrl_info(ctrl, "Can't get msi for the hotplug controller\n"); - ctrl_info(ctrl, "Use INTx for the hotplug controller\n"); -+ } else { -+ pci_set_master(pdev); - } - - rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, -diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c -index d5bf36ec8a75..34367d172961 100644 ---- a/drivers/s390/scsi/zfcp_dbf.c -+++ b/drivers/s390/scsi/zfcp_dbf.c -@@ -3,7 +3,7 @@ - * - * Debug traces for zfcp. - * -- * Copyright IBM Corp. 2002, 2016 -+ * Copyright IBM Corp. 2002, 2017 - */ - - #define KMSG_COMPONENT "zfcp" -@@ -447,6 +447,7 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag, - struct fc_ct_hdr *reqh = sg_virt(ct_els->req); - struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1); - struct scatterlist *resp_entry = ct_els->resp; -+ struct fc_ct_hdr *resph; - struct fc_gpn_ft_resp *acc; - int max_entries, x, last = 0; - -@@ -473,6 +474,13 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag, - return len; /* not GPN_FT response so do not cap */ - - acc = sg_virt(resp_entry); -+ -+ /* cap all but accept CT responses to at least the CT header */ -+ resph = (struct fc_ct_hdr *)acc; -+ if ((ct_els->status) || -+ (resph->ct_cmd != cpu_to_be16(FC_FS_ACC))) -+ return max(FC_CT_HDR_LEN, ZFCP_DBF_SAN_MAX_PAYLOAD); -+ - max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp)) - + 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one - * to account for header as 1st pseudo "entry" */; -@@ -555,8 +563,8 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, - rec->scsi_retries = sc->retries; - rec->scsi_allowed = sc->allowed; - rec->scsi_id = sc->device->id; -- /* struct zfcp_dbf_scsi needs to be updated to handle 64bit LUNs */ - rec->scsi_lun = (u32)sc->device->lun; -+ rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); - rec->host_scribble = (unsigned long)sc->host_scribble; - - memcpy(rec->scsi_opcode, sc->cmnd, -@@ -564,19 +572,32 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, - - if (fsf) { - rec->fsf_req_id = fsf->req_id; -+ rec->pl_len = FCP_RESP_WITH_EXT; - fcp_rsp = (struct fcp_resp_with_ext *) - &(fsf->qtcb->bottom.io.fcp_rsp); -+ /* mandatory parts of FCP_RSP IU in this SCSI record */ - memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT); - if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) { - fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1]; - rec->fcp_rsp_info = fcp_rsp_info->rsp_code; -+ rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_rsp_len); - } - if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) { -- rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE, -- (u16)ZFCP_DBF_PAY_MAX_REC); -- zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len, -- "fcp_sns", fsf->req_id); -+ rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len); - } -+ /* complete FCP_RSP IU in associated PAYload record -+ * but only if there are optional parts -+ */ -+ if (fcp_rsp->resp.fr_flags != 0) -+ zfcp_dbf_pl_write( -+ dbf, fcp_rsp, -+ /* at least one full PAY record -+ * but not beyond hardware response field -+ */ -+ min_t(u16, max_t(u16, rec->pl_len, -+ ZFCP_DBF_PAY_MAX_REC), -+ FSF_FCP_RSP_SIZE), -+ "fcp_riu", fsf->req_id); - } - - debug_event(dbf->scsi, level, rec, sizeof(*rec)); -diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h -index db186d44cfaf..b60667c145fd 100644 ---- a/drivers/s390/scsi/zfcp_dbf.h -+++ b/drivers/s390/scsi/zfcp_dbf.h -@@ -2,7 +2,7 @@ - * zfcp device driver - * debug feature declarations - * -- * Copyright IBM Corp. 2008, 2016 -+ * Copyright IBM Corp. 2008, 2017 - */ - - #ifndef ZFCP_DBF_H -@@ -204,7 +204,7 @@ enum zfcp_dbf_scsi_id { - * @id: unique number of recovery record type - * @tag: identifier string specifying the location of initiation - * @scsi_id: scsi device id -- * @scsi_lun: scsi device logical unit number -+ * @scsi_lun: scsi device logical unit number, low part of 64 bit, old 32 bit - * @scsi_result: scsi result - * @scsi_retries: current retry number of scsi request - * @scsi_allowed: allowed retries -@@ -214,6 +214,7 @@ enum zfcp_dbf_scsi_id { - * @host_scribble: LLD specific data attached to SCSI request - * @pl_len: length of paload stored as zfcp_dbf_pay - * @fsf_rsp: response for fsf request -+ * @scsi_lun_64_hi: scsi device logical unit number, high part of 64 bit - */ - struct zfcp_dbf_scsi { - u8 id; -@@ -230,6 +231,7 @@ struct zfcp_dbf_scsi { - u64 host_scribble; - u16 pl_len; - struct fcp_resp_with_ext fcp_rsp; -+ u32 scsi_lun_64_hi; - } __packed; - - /** -@@ -323,7 +325,11 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req) - { - struct fsf_qtcb *qtcb = req->qtcb; - -- if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && -+ if (unlikely(req->status & (ZFCP_STATUS_FSFREQ_DISMISSED | -+ ZFCP_STATUS_FSFREQ_ERROR))) { -+ zfcp_dbf_hba_fsf_resp("fs_rerr", 3, req); -+ -+ } else if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && - (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { - zfcp_dbf_hba_fsf_resp("fs_perr", 1, req); - -@@ -401,7 +407,8 @@ void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd, - * @flag: indicates type of reset (Target Reset, Logical Unit Reset) - */ - static inline --void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag) -+void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag, -+ struct zfcp_fsf_req *fsf_req) - { - char tmp_tag[ZFCP_DBF_TAG_LEN]; - -@@ -411,7 +418,7 @@ void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag) - memcpy(tmp_tag, "lr_", 3); - - memcpy(&tmp_tag[3], tag, 4); -- _zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL); -+ _zfcp_dbf_scsi(tmp_tag, 1, scmnd, fsf_req); - } - - /** -diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h -index df2b541c8287..a2275825186f 100644 ---- a/drivers/s390/scsi/zfcp_fc.h -+++ b/drivers/s390/scsi/zfcp_fc.h -@@ -4,7 +4,7 @@ - * Fibre Channel related definitions and inline functions for the zfcp - * device driver - * -- * Copyright IBM Corp. 2009 -+ * Copyright IBM Corp. 2009, 2017 - */ - - #ifndef ZFCP_FC_H -@@ -279,6 +279,10 @@ void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp, - !(rsp_flags & FCP_SNS_LEN_VAL) && - fcp_rsp->resp.fr_status == SAM_STAT_GOOD) - set_host_byte(scsi, DID_ERROR); -+ } else if (unlikely(rsp_flags & FCP_RESID_OVER)) { -+ /* FCP_DL was not sufficient for SCSI data length */ -+ if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD) -+ set_host_byte(scsi, DID_ERROR); - } - } - -diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c -index 27ff38f839fc..1964391db904 100644 ---- a/drivers/s390/scsi/zfcp_fsf.c -+++ b/drivers/s390/scsi/zfcp_fsf.c -@@ -928,8 +928,8 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) - - switch (header->fsf_status) { - case FSF_GOOD: -- zfcp_dbf_san_res("fsscth2", req); - ct->status = 0; -+ zfcp_dbf_san_res("fsscth2", req); - break; - case FSF_SERVICE_CLASS_NOT_SUPPORTED: - zfcp_fsf_class_not_supp(req); -@@ -1109,8 +1109,8 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) - - switch (header->fsf_status) { - case FSF_GOOD: -- zfcp_dbf_san_res("fsselh1", req); - send_els->status = 0; -+ zfcp_dbf_san_res("fsselh1", req); - break; - case FSF_SERVICE_CLASS_NOT_SUPPORTED: - zfcp_fsf_class_not_supp(req); -@@ -2258,7 +2258,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) - fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd; - zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0); - -- if (scsi_prot_sg_count(scsi_cmnd)) { -+ if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) && -+ scsi_prot_sg_count(scsi_cmnd)) { - zfcp_qdio_set_data_div(qdio, &req->qdio_req, - scsi_prot_sg_count(scsi_cmnd)); - retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, -diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c -index 07ffdbb5107f..9bd9b9a29dfc 100644 ---- a/drivers/s390/scsi/zfcp_scsi.c -+++ b/drivers/s390/scsi/zfcp_scsi.c -@@ -3,7 +3,7 @@ - * - * Interface to Linux SCSI midlayer. - * -- * Copyright IBM Corp. 2002, 2016 -+ * Copyright IBM Corp. 2002, 2017 - */ - - #define KMSG_COMPONENT "zfcp" -@@ -273,25 +273,29 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) - - zfcp_erp_wait(adapter); - ret = fc_block_scsi_eh(scpnt); -- if (ret) -+ if (ret) { -+ zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags, NULL); - return ret; -+ } - - if (!(atomic_read(&adapter->status) & - ZFCP_STATUS_COMMON_RUNNING)) { -- zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags); -+ zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags, NULL); - return SUCCESS; - } - } -- if (!fsf_req) -+ if (!fsf_req) { -+ zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags, NULL); - return FAILED; -+ } - - wait_for_completion(&fsf_req->completion); - - if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { -- zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags); -+ zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags, fsf_req); - retval = FAILED; - } else { -- zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags); -+ zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags, fsf_req); - zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags); - } - -diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c -index 17c440b9d086..6835bae33ec4 100644 ---- a/drivers/scsi/megaraid/megaraid_sas_base.c -+++ b/drivers/scsi/megaraid/megaraid_sas_base.c -@@ -1824,9 +1824,12 @@ static void megasas_complete_outstanding_ioctls(struct megasas_instance *instanc - if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) { - cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; - if (cmd_mfi->sync_cmd && -- cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) -+ (cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)) { -+ cmd_mfi->frame->hdr.cmd_status = -+ MFI_STAT_WRONG_STATE; - megasas_complete_cmd(instance, - cmd_mfi, DID_OK); -+ } - } - } - } else { -@@ -5094,6 +5097,14 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, - prev_aen.word = - le32_to_cpu(instance->aen_cmd->frame->dcmd.mbox.w[1]); - -+ if ((curr_aen.members.class < MFI_EVT_CLASS_DEBUG) || -+ (curr_aen.members.class > MFI_EVT_CLASS_DEAD)) { -+ dev_info(&instance->pdev->dev, -+ "%s %d out of range class %d send by application\n", -+ __func__, __LINE__, curr_aen.members.class); -+ return 0; -+ } -+ - /* - * A class whose enum value is smaller is inclusive of all - * higher values. If a PROGRESS (= -1) was previously -diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c -index 1ed85dfc008d..ac12ee844bfc 100644 ---- a/drivers/scsi/qla2xxx/qla_attr.c -+++ b/drivers/scsi/qla2xxx/qla_attr.c -@@ -404,6 +404,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, - return -EINVAL; - if (start > ha->optrom_size) - return -EINVAL; -+ if (size > ha->optrom_size - start) -+ size = ha->optrom_size - start; - - mutex_lock(&ha->optrom_mutex); - switch (val) { -@@ -429,8 +431,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, - } - - ha->optrom_region_start = start; -- ha->optrom_region_size = start + size > ha->optrom_size ? -- ha->optrom_size - start : size; -+ ha->optrom_region_size = start + size; - - ha->optrom_state = QLA_SREADING; - ha->optrom_buffer = vmalloc(ha->optrom_region_size); -@@ -503,8 +504,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, - } - - ha->optrom_region_start = start; -- ha->optrom_region_size = start + size > ha->optrom_size ? -- ha->optrom_size - start : size; -+ ha->optrom_region_size = start + size; - - ha->optrom_state = QLA_SWRITING; - ha->optrom_buffer = vmalloc(ha->optrom_region_size); -diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c -index 71325972e503..39e8b5dc23fa 100644 ---- a/drivers/scsi/sg.c -+++ b/drivers/scsi/sg.c -@@ -133,7 +133,7 @@ struct sg_device; /* forward declarations */ - struct sg_fd; - - typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ -- struct sg_request *nextrp; /* NULL -> tail request (slist) */ -+ struct list_head entry; /* list entry */ - struct sg_fd *parentfp; /* NULL -> not in use */ - Sg_scatter_hold data; /* hold buffer, perhaps scatter list */ - sg_io_hdr_t header; /* scsi command+info, see */ -@@ -157,8 +157,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ - int timeout; /* defaults to SG_DEFAULT_TIMEOUT */ - int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */ - Sg_scatter_hold reserve; /* buffer held for this file descriptor */ -- unsigned save_scat_len; /* original length of trunc. scat. element */ -- Sg_request *headrp; /* head of request slist, NULL->empty */ -+ struct list_head rq_list; /* head of request list */ - struct fasync_struct *async_qp; /* used by asynchronous notification */ - Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */ - char low_dma; /* as in parent but possibly overridden to 1 */ -@@ -840,6 +839,39 @@ static int max_sectors_bytes(struct request_queue *q) - return max_sectors << 9; - } - -+static void -+sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo) -+{ -+ Sg_request *srp; -+ int val; -+ unsigned int ms; -+ -+ val = 0; -+ list_for_each_entry(srp, &sfp->rq_list, entry) { -+ if (val > SG_MAX_QUEUE) -+ break; -+ rinfo[val].req_state = srp->done + 1; -+ rinfo[val].problem = -+ srp->header.masked_status & -+ srp->header.host_status & -+ srp->header.driver_status; -+ if (srp->done) -+ rinfo[val].duration = -+ srp->header.duration; -+ else { -+ ms = jiffies_to_msecs(jiffies); -+ rinfo[val].duration = -+ (ms > srp->header.duration) ? -+ (ms - srp->header.duration) : 0; -+ } -+ rinfo[val].orphan = srp->orphan; -+ rinfo[val].sg_io_owned = srp->sg_io_owned; -+ rinfo[val].pack_id = srp->header.pack_id; -+ rinfo[val].usr_ptr = srp->header.usr_ptr; -+ val++; -+ } -+} -+ - static long - sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - { -@@ -951,7 +983,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - if (!access_ok(VERIFY_WRITE, ip, sizeof (int))) - return -EFAULT; - read_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (srp = sfp->headrp; srp; srp = srp->nextrp) { -+ list_for_each_entry(srp, &sfp->rq_list, entry) { - if ((1 == srp->done) && (!srp->sg_io_owned)) { - read_unlock_irqrestore(&sfp->rq_list_lock, - iflags); -@@ -964,7 +996,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - return 0; - case SG_GET_NUM_WAITING: - read_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) { -+ val = 0; -+ list_for_each_entry(srp, &sfp->rq_list, entry) { - if ((1 == srp->done) && (!srp->sg_io_owned)) - ++val; - } -@@ -1032,42 +1065,15 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) - return -EFAULT; - else { - sg_req_info_t *rinfo; -- unsigned int ms; - -- rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, -- GFP_KERNEL); -+ rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE, -+ GFP_KERNEL); - if (!rinfo) - return -ENOMEM; - read_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE; -- ++val, srp = srp ? srp->nextrp : srp) { -- memset(&rinfo[val], 0, SZ_SG_REQ_INFO); -- if (srp) { -- rinfo[val].req_state = srp->done + 1; -- rinfo[val].problem = -- srp->header.masked_status & -- srp->header.host_status & -- srp->header.driver_status; -- if (srp->done) -- rinfo[val].duration = -- srp->header.duration; -- else { -- ms = jiffies_to_msecs(jiffies); -- rinfo[val].duration = -- (ms > srp->header.duration) ? -- (ms - srp->header.duration) : 0; -- } -- rinfo[val].orphan = srp->orphan; -- rinfo[val].sg_io_owned = -- srp->sg_io_owned; -- rinfo[val].pack_id = -- srp->header.pack_id; -- rinfo[val].usr_ptr = -- srp->header.usr_ptr; -- } -- } -+ sg_fill_request_table(sfp, rinfo); - read_unlock_irqrestore(&sfp->rq_list_lock, iflags); -- result = __copy_to_user(p, rinfo, -+ result = __copy_to_user(p, rinfo, - SZ_SG_REQ_INFO * SG_MAX_QUEUE); - result = result ? -EFAULT : 0; - kfree(rinfo); -@@ -1173,7 +1179,7 @@ sg_poll(struct file *filp, poll_table * wait) - return POLLERR; - poll_wait(filp, &sfp->read_wait, wait); - read_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (srp = sfp->headrp; srp; srp = srp->nextrp) { -+ list_for_each_entry(srp, &sfp->rq_list, entry) { - /* if any read waiting, flag it */ - if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned)) - res = POLLIN | POLLRDNORM; -@@ -2059,7 +2065,6 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) - req_schp->pages = NULL; - req_schp->page_order = 0; - req_schp->sglist_len = 0; -- sfp->save_scat_len = 0; - srp->res_used = 0; - /* Called without mutex lock to avoid deadlock */ - sfp->res_in_use = 0; -@@ -2072,7 +2077,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id) - unsigned long iflags; - - write_lock_irqsave(&sfp->rq_list_lock, iflags); -- for (resp = sfp->headrp; resp; resp = resp->nextrp) { -+ list_for_each_entry(resp, &sfp->rq_list, entry) { - /* look for requests that are ready + not SG_IO owned */ - if ((1 == resp->done) && (!resp->sg_io_owned) && - ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { -@@ -2090,70 +2095,45 @@ sg_add_request(Sg_fd * sfp) - { - int k; - unsigned long iflags; -- Sg_request *resp; - Sg_request *rp = sfp->req_arr; - - write_lock_irqsave(&sfp->rq_list_lock, iflags); -- resp = sfp->headrp; -- if (!resp) { -- memset(rp, 0, sizeof (Sg_request)); -- rp->parentfp = sfp; -- resp = rp; -- sfp->headrp = resp; -- } else { -- if (0 == sfp->cmd_q) -- resp = NULL; /* command queuing disallowed */ -- else { -- for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { -- if (!rp->parentfp) -- break; -- } -- if (k < SG_MAX_QUEUE) { -- memset(rp, 0, sizeof (Sg_request)); -- rp->parentfp = sfp; -- while (resp->nextrp) -- resp = resp->nextrp; -- resp->nextrp = rp; -- resp = rp; -- } else -- resp = NULL; -+ if (!list_empty(&sfp->rq_list)) { -+ if (!sfp->cmd_q) -+ goto out_unlock; -+ -+ for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { -+ if (!rp->parentfp) -+ break; - } -+ if (k >= SG_MAX_QUEUE) -+ goto out_unlock; - } -- if (resp) { -- resp->nextrp = NULL; -- resp->header.duration = jiffies_to_msecs(jiffies); -- } -+ memset(rp, 0, sizeof (Sg_request)); -+ rp->parentfp = sfp; -+ rp->header.duration = jiffies_to_msecs(jiffies); -+ list_add_tail(&rp->entry, &sfp->rq_list); - write_unlock_irqrestore(&sfp->rq_list_lock, iflags); -- return resp; -+ return rp; -+out_unlock: -+ write_unlock_irqrestore(&sfp->rq_list_lock, iflags); -+ return NULL; - } - - /* Return of 1 for found; 0 for not found */ - static int - sg_remove_request(Sg_fd * sfp, Sg_request * srp) - { -- Sg_request *prev_rp; -- Sg_request *rp; - unsigned long iflags; - int res = 0; - -- if ((!sfp) || (!srp) || (!sfp->headrp)) -+ if (!sfp || !srp || list_empty(&sfp->rq_list)) - return res; - write_lock_irqsave(&sfp->rq_list_lock, iflags); -- prev_rp = sfp->headrp; -- if (srp == prev_rp) { -- sfp->headrp = prev_rp->nextrp; -- prev_rp->parentfp = NULL; -+ if (!list_empty(&srp->entry)) { -+ list_del(&srp->entry); -+ srp->parentfp = NULL; - res = 1; -- } else { -- while ((rp = prev_rp->nextrp)) { -- if (srp == rp) { -- prev_rp->nextrp = rp->nextrp; -- rp->parentfp = NULL; -- res = 1; -- break; -- } -- prev_rp = rp; -- } - } - write_unlock_irqrestore(&sfp->rq_list_lock, iflags); - return res; -@@ -2172,7 +2152,7 @@ sg_add_sfp(Sg_device * sdp) - - init_waitqueue_head(&sfp->read_wait); - rwlock_init(&sfp->rq_list_lock); -- -+ INIT_LIST_HEAD(&sfp->rq_list); - kref_init(&sfp->f_ref); - mutex_init(&sfp->f_mutex); - sfp->timeout = SG_DEFAULT_TIMEOUT; -@@ -2213,10 +2193,13 @@ sg_remove_sfp_usercontext(struct work_struct *work) - { - struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); - struct sg_device *sdp = sfp->parentdp; -+ Sg_request *srp; - - /* Cleanup any responses which were never read(). */ -- while (sfp->headrp) -- sg_finish_rem_req(sfp->headrp); -+ while (!list_empty(&sfp->rq_list)) { -+ srp = list_first_entry(&sfp->rq_list, Sg_request, entry); -+ sg_finish_rem_req(srp); -+ } - - if (sfp->reserve.bufflen > 0) { - SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, -@@ -2619,7 +2602,7 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v) - /* must be called while holding sg_index_lock */ - static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) - { -- int k, m, new_interface, blen, usg; -+ int k, new_interface, blen, usg; - Sg_request *srp; - Sg_fd *fp; - const sg_io_hdr_t *hp; -@@ -2639,13 +2622,11 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) - seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n", - (int) fp->cmd_q, (int) fp->force_packid, - (int) fp->keep_orphan); -- for (m = 0, srp = fp->headrp; -- srp != NULL; -- ++m, srp = srp->nextrp) { -+ list_for_each_entry(srp, &fp->rq_list, entry) { - hp = &srp->header; - new_interface = (hp->interface_id == '\0') ? 0 : 1; - if (srp->res_used) { -- if (new_interface && -+ if (new_interface && - (SG_FLAG_MMAP_IO & hp->flags)) - cp = " mmap>> "; - else -@@ -2676,7 +2657,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) - seq_printf(s, "ms sgat=%d op=0x%02x\n", usg, - (int) srp->data.cmd_opcode); - } -- if (0 == m) -+ if (list_empty(&fp->rq_list)) - seq_puts(s, " No requests active\n"); - read_unlock(&fp->rq_list_lock); - } -diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c -index cd5c1c060481..6df2841cb7f9 100644 ---- a/drivers/scsi/storvsc_drv.c -+++ b/drivers/scsi/storvsc_drv.c -@@ -1511,6 +1511,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) - ret = storvsc_do_io(dev, cmd_request); - - if (ret == -EAGAIN) { -+ if (payload_sz > sizeof(cmd_request->mpb)) -+ kfree(payload); - /* no more space */ - return SCSI_MLQUEUE_DEVICE_BUSY; - } -diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c -index fb31eecb708d..8f3566cde3eb 100644 ---- a/drivers/tty/tty_buffer.c -+++ b/drivers/tty/tty_buffer.c -@@ -361,6 +361,32 @@ int tty_insert_flip_string_flags(struct tty_port *port, - } - EXPORT_SYMBOL(tty_insert_flip_string_flags); - -+/** -+ * __tty_insert_flip_char - Add one character to the tty buffer -+ * @port: tty port -+ * @ch: character -+ * @flag: flag byte -+ * -+ * Queue a single byte to the tty buffering, with an optional flag. -+ * This is the slow path of tty_insert_flip_char. -+ */ -+int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) -+{ -+ struct tty_buffer *tb; -+ int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0; -+ -+ if (!__tty_buffer_request_room(port, 1, flags)) -+ return 0; -+ -+ tb = port->buf.tail; -+ if (~tb->flags & TTYB_NORMAL) -+ *flag_buf_ptr(tb, tb->used) = flag; -+ *char_buf_ptr(tb, tb->used++) = ch; -+ -+ return 1; -+} -+EXPORT_SYMBOL(__tty_insert_flip_char); -+ - /** - * tty_schedule_flip - push characters to ldisc - * @port: tty port to push from -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 68345a9e59b8..32941cd6d34b 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2205,6 +2205,7 @@ static void ext4_orphan_cleanup(struct super_block *sb, - unsigned int s_flags = sb->s_flags; - int nr_orphans = 0, nr_truncates = 0; - #ifdef CONFIG_QUOTA -+ int quota_update = 0; - int i; - #endif - if (!es->s_last_orphan) { -@@ -2243,14 +2244,32 @@ static void ext4_orphan_cleanup(struct super_block *sb, - #ifdef CONFIG_QUOTA - /* Needed for iput() to work correctly and not trash data */ - sb->s_flags |= MS_ACTIVE; -- /* Turn on quotas so that they are updated correctly */ -+ -+ /* -+ * Turn on quotas which were not enabled for read-only mounts if -+ * filesystem has quota feature, so that they are updated correctly. -+ */ -+ if (ext4_has_feature_quota(sb) && (s_flags & MS_RDONLY)) { -+ int ret = ext4_enable_quotas(sb); -+ -+ if (!ret) -+ quota_update = 1; -+ else -+ ext4_msg(sb, KERN_ERR, -+ "Cannot turn on quotas: error %d", ret); -+ } -+ -+ /* Turn on journaled quotas used for old sytle */ - for (i = 0; i < EXT4_MAXQUOTAS; i++) { - if (EXT4_SB(sb)->s_qf_names[i]) { - int ret = ext4_quota_on_mount(sb, i); -- if (ret < 0) -+ -+ if (!ret) -+ quota_update = 1; -+ else - ext4_msg(sb, KERN_ERR, - "Cannot turn on journaled " -- "quota: error %d", ret); -+ "quota: type %d: error %d", i, ret); - } - } - #endif -@@ -2309,10 +2328,12 @@ static void ext4_orphan_cleanup(struct super_block *sb, - ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up", - PLURAL(nr_truncates)); - #ifdef CONFIG_QUOTA -- /* Turn quotas off */ -- for (i = 0; i < EXT4_MAXQUOTAS; i++) { -- if (sb_dqopt(sb)->files[i]) -- dquot_quota_off(sb, i); -+ /* Turn off quotas if they were enabled for orphan cleanup */ -+ if (quota_update) { -+ for (i = 0; i < EXT4_MAXQUOTAS; i++) { -+ if (sb_dqopt(sb)->files[i]) -+ dquot_quota_off(sb, i); -+ } - } - #endif - sb->s_flags = s_flags; /* Restore MS_RDONLY status */ -@@ -5120,6 +5141,9 @@ static int ext4_enable_quotas(struct super_block *sb) - err = ext4_quota_enable(sb, type, QFMT_VFS_V1, - DQUOT_USAGE_ENABLED); - if (err) { -+ for (type--; type >= 0; type--) -+ dquot_quota_off(sb, type); -+ - ext4_warning(sb, - "Failed to enable quota tracking " - "(type=%d, err=%d). Please run " -diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c -index cbf74f47cce8..e32f349f341b 100644 ---- a/fs/f2fs/recovery.c -+++ b/fs/f2fs/recovery.c -@@ -276,7 +276,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, - return 0; - - /* Get the previous summary */ -- for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { -+ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { - struct curseg_info *curseg = CURSEG_I(sbi, i); - if (curseg->segno == segno) { - sum = curseg->sum_blk->entries[blkoff]; -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index c7f1ce41442a..9e5a6842346e 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -1145,9 +1145,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, - - static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) - { -- struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); -- -- lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); -+ lockdep_assert_held(&stp->st_stid.sc_client->cl_lock); - - list_del_init(&stp->st_locks); - nfs4_unhash_stid(&stp->st_stid); -@@ -1156,12 +1154,12 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) - - static void release_lock_stateid(struct nfs4_ol_stateid *stp) - { -- struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); -+ struct nfs4_client *clp = stp->st_stid.sc_client; - bool unhashed; - -- spin_lock(&oo->oo_owner.so_client->cl_lock); -+ spin_lock(&clp->cl_lock); - unhashed = unhash_lock_stateid(stp); -- spin_unlock(&oo->oo_owner.so_client->cl_lock); -+ spin_unlock(&clp->cl_lock); - if (unhashed) - nfs4_put_stid(&stp->st_stid); - } -diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h -index c28dd523f96e..d43837f2ce3a 100644 ---- a/include/linux/tty_flip.h -+++ b/include/linux/tty_flip.h -@@ -12,6 +12,7 @@ extern int tty_prepare_flip_string(struct tty_port *port, - unsigned char **chars, size_t size); - extern void tty_flip_buffer_push(struct tty_port *port); - void tty_schedule_flip(struct tty_port *port); -+int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag); - - static inline int tty_insert_flip_char(struct tty_port *port, - unsigned char ch, char flag) -@@ -26,7 +27,7 @@ static inline int tty_insert_flip_char(struct tty_port *port, - *char_buf_ptr(tb, tb->used++) = ch; - return 1; - } -- return tty_insert_flip_string_flags(port, &ch, &flag, 1); -+ return __tty_insert_flip_char(port, ch, flag); - } - - static inline int tty_insert_flip_string(struct tty_port *port, -diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h -index ac42bbb37b2d..c26a6e4dc306 100644 ---- a/include/net/inet_frag.h -+++ b/include/net/inet_frag.h -@@ -1,14 +1,9 @@ - #ifndef __NET_FRAG_H__ - #define __NET_FRAG_H__ - --#include -- - struct netns_frags { -- /* The percpu_counter "mem" need to be cacheline aligned. -- * mem.count must not share cacheline with other writers -- */ -- struct percpu_counter mem ____cacheline_aligned_in_smp; -- -+ /* Keep atomic mem on separate cachelines in structs that include it */ -+ atomic_t mem ____cacheline_aligned_in_smp; - /* sysctls */ - int timeout; - int high_thresh; -@@ -108,15 +103,10 @@ struct inet_frags { - int inet_frags_init(struct inet_frags *); - void inet_frags_fini(struct inet_frags *); - --static inline int inet_frags_init_net(struct netns_frags *nf) --{ -- return percpu_counter_init(&nf->mem, 0, GFP_KERNEL); --} --static inline void inet_frags_uninit_net(struct netns_frags *nf) -+static inline void inet_frags_init_net(struct netns_frags *nf) - { -- percpu_counter_destroy(&nf->mem); -+ atomic_set(&nf->mem, 0); - } -- - void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); - - void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); -@@ -140,37 +130,24 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q) - - /* Memory Tracking Functions. */ - --/* The default percpu_counter batch size is not big enough to scale to -- * fragmentation mem acct sizes. -- * The mem size of a 64K fragment is approx: -- * (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes -- */ --static unsigned int frag_percpu_counter_batch = 130000; -- - static inline int frag_mem_limit(struct netns_frags *nf) - { -- return percpu_counter_read(&nf->mem); -+ return atomic_read(&nf->mem); - } - - static inline void sub_frag_mem_limit(struct netns_frags *nf, int i) - { -- __percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch); -+ atomic_sub(i, &nf->mem); - } - - static inline void add_frag_mem_limit(struct netns_frags *nf, int i) - { -- __percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch); -+ atomic_add(i, &nf->mem); - } - --static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf) -+static inline int sum_frag_mem_limit(struct netns_frags *nf) - { -- unsigned int res; -- -- local_bh_disable(); -- res = percpu_counter_sum_positive(&nf->mem); -- local_bh_enable(); -- -- return res; -+ return atomic_read(&nf->mem); - } - - /* RFC 3168 support : -diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h -index fb961a576abe..fa5e703a14ed 100644 ---- a/include/net/ip6_fib.h -+++ b/include/net/ip6_fib.h -@@ -68,6 +68,7 @@ struct fib6_node { - __u16 fn_flags; - int fn_sernum; - struct rt6_info *rr_ptr; -+ struct rcu_head rcu; - }; - - #ifndef CONFIG_IPV6_SUBTREES -@@ -102,7 +103,7 @@ struct rt6_info { - * the same cache line. - */ - struct fib6_table *rt6i_table; -- struct fib6_node *rt6i_node; -+ struct fib6_node __rcu *rt6i_node; - - struct in6_addr rt6i_gateway; - -@@ -165,13 +166,40 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout) - rt0->rt6i_flags |= RTF_EXPIRES; - } - -+/* Function to safely get fn->sernum for passed in rt -+ * and store result in passed in cookie. -+ * Return true if we can get cookie safely -+ * Return false if not -+ */ -+static inline bool rt6_get_cookie_safe(const struct rt6_info *rt, -+ u32 *cookie) -+{ -+ struct fib6_node *fn; -+ bool status = false; -+ -+ rcu_read_lock(); -+ fn = rcu_dereference(rt->rt6i_node); -+ -+ if (fn) { -+ *cookie = fn->fn_sernum; -+ status = true; -+ } -+ -+ rcu_read_unlock(); -+ return status; -+} -+ - static inline u32 rt6_get_cookie(const struct rt6_info *rt) - { -+ u32 cookie = 0; -+ - if (rt->rt6i_flags & RTF_PCPU || - (unlikely(rt->dst.flags & DST_NOCACHE) && rt->dst.from)) - rt = (struct rt6_info *)(rt->dst.from); - -- return rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; -+ rt6_get_cookie_safe(rt, &cookie); -+ -+ return cookie; - } - - static inline void ip6_rt_put(struct rt6_info *rt) -diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index eba904bae48c..38d73a6e2857 100644 ---- a/kernel/trace/ftrace.c -+++ b/kernel/trace/ftrace.c -@@ -2667,13 +2667,14 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) - - if (!command || !ftrace_enabled) { - /* -- * If these are control ops, they still need their -- * per_cpu field freed. Since, function tracing is -+ * If these are dynamic or control ops, they still -+ * need their data freed. Since, function tracing is - * not currently active, we can just free them - * without synchronizing all CPUs. - */ -- if (ops->flags & FTRACE_OPS_FL_CONTROL) -- control_ops_free(ops); -+ if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_CONTROL)) -+ goto free_ops; -+ - return 0; - } - -@@ -2728,6 +2729,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command) - if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_CONTROL)) { - schedule_on_each_cpu(ftrace_sync); - -+ free_ops: - arch_ftrace_trampoline_free(ops); - - if (ops->flags & FTRACE_OPS_FL_CONTROL) -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index d59ebd9d21df..4743066010c4 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -5237,7 +5237,7 @@ static int tracing_set_clock(struct trace_array *tr, const char *clockstr) - tracing_reset_online_cpus(&tr->trace_buffer); - - #ifdef CONFIG_TRACER_MAX_TRACE -- if (tr->flags & TRACE_ARRAY_FL_GLOBAL && tr->max_buffer.buffer) -+ if (tr->max_buffer.buffer) - ring_buffer_set_clock(tr->max_buffer.buffer, trace_clocks[i].func); - tracing_reset_online_cpus(&tr->max_buffer); - #endif -diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c -index b0f86ea77881..ca70d11b8aa7 100644 ---- a/kernel/trace/trace_selftest.c -+++ b/kernel/trace/trace_selftest.c -@@ -272,7 +272,7 @@ static int trace_selftest_ops(struct trace_array *tr, int cnt) - goto out_free; - if (cnt > 1) { - if (trace_selftest_test_global_cnt == 0) -- goto out; -+ goto out_free; - } - if (trace_selftest_test_dyn_cnt == 0) - goto out_free; -diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c -index 6b437e8760d3..12e8cf4bda9f 100644 ---- a/net/ieee802154/6lowpan/reassembly.c -+++ b/net/ieee802154/6lowpan/reassembly.c -@@ -580,19 +580,14 @@ static int __net_init lowpan_frags_init_net(struct net *net) - { - struct netns_ieee802154_lowpan *ieee802154_lowpan = - net_ieee802154_lowpan(net); -- int res; - - ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; - ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; - ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; - -- res = inet_frags_init_net(&ieee802154_lowpan->frags); -- if (res) -- return res; -- res = lowpan_frags_ns_sysctl_register(net); -- if (res) -- inet_frags_uninit_net(&ieee802154_lowpan->frags); -- return res; -+ inet_frags_init_net(&ieee802154_lowpan->frags); -+ -+ return lowpan_frags_ns_sysctl_register(net); - } - - static void __net_exit lowpan_frags_exit_net(struct net *net) -diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c -index fe144dae7372..c5fb2f694ed0 100644 ---- a/net/ipv4/inet_fragment.c -+++ b/net/ipv4/inet_fragment.c -@@ -234,10 +234,8 @@ evict_again: - cond_resched(); - - if (read_seqretry(&f->rnd_seqlock, seq) || -- percpu_counter_sum(&nf->mem)) -+ sum_frag_mem_limit(nf)) - goto evict_again; -- -- percpu_counter_destroy(&nf->mem); - } - EXPORT_SYMBOL(inet_frags_exit_net); - -diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c -index b8a0607dab96..e2e162432aa3 100644 ---- a/net/ipv4/ip_fragment.c -+++ b/net/ipv4/ip_fragment.c -@@ -840,8 +840,6 @@ static void __init ip4_frags_ctl_register(void) - - static int __net_init ipv4_frags_init_net(struct net *net) - { -- int res; -- - /* Fragment cache limits. - * - * The fragment memory accounting code, (tries to) account for -@@ -865,13 +863,9 @@ static int __net_init ipv4_frags_init_net(struct net *net) - */ - net->ipv4.frags.timeout = IP_FRAG_TIME; - -- res = inet_frags_init_net(&net->ipv4.frags); -- if (res) -- return res; -- res = ip4_frags_ns_ctl_register(net); -- if (res) -- inet_frags_uninit_net(&net->ipv4.frags); -- return res; -+ inet_frags_init_net(&net->ipv4.frags); -+ -+ return ip4_frags_ns_ctl_register(net); - } - - static void __net_exit ipv4_frags_exit_net(struct net *net) -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 0870a86e9d96..5597120c8ffd 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -2260,6 +2260,10 @@ int tcp_disconnect(struct sock *sk, int flags) - tcp_set_ca_state(sk, TCP_CA_Open); - tcp_clear_retrans(tp); - inet_csk_delack_init(sk); -+ /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 -+ * issue in __tcp_select_window() -+ */ -+ icsk->icsk_ack.rcv_mss = TCP_MIN_MSS; - tcp_init_send_head(sk); - memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); - __sk_dst_reset(sk); -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 735b22b1b4ea..92174881844d 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -5152,7 +5152,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) - * our DAD process, so we don't need - * to do it again - */ -- if (!(ifp->rt->rt6i_node)) -+ if (!rcu_access_pointer(ifp->rt->rt6i_node)) - ip6_ins_rt(ifp->rt); - if (ifp->idev->cnf.forwarding) - addrconf_join_anycast(ifp); -diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c -index aad8cdf15472..c23e02a7ccb0 100644 ---- a/net/ipv6/ip6_fib.c -+++ b/net/ipv6/ip6_fib.c -@@ -150,11 +150,23 @@ static struct fib6_node *node_alloc(void) - return fn; - } - --static void node_free(struct fib6_node *fn) -+static void node_free_immediate(struct fib6_node *fn) -+{ -+ kmem_cache_free(fib6_node_kmem, fn); -+} -+ -+static void node_free_rcu(struct rcu_head *head) - { -+ struct fib6_node *fn = container_of(head, struct fib6_node, rcu); -+ - kmem_cache_free(fib6_node_kmem, fn); - } - -+static void node_free(struct fib6_node *fn) -+{ -+ call_rcu(&fn->rcu, node_free_rcu); -+} -+ - static void rt6_rcu_free(struct rt6_info *rt) - { - call_rcu(&rt->dst.rcu_head, dst_rcu_free); -@@ -191,6 +203,12 @@ static void rt6_release(struct rt6_info *rt) - } - } - -+static void fib6_free_table(struct fib6_table *table) -+{ -+ inetpeer_invalidate_tree(&table->tb6_peers); -+ kfree(table); -+} -+ - static void fib6_link_table(struct net *net, struct fib6_table *tb) - { - unsigned int h; -@@ -588,9 +606,9 @@ insert_above: - - if (!in || !ln) { - if (in) -- node_free(in); -+ node_free_immediate(in); - if (ln) -- node_free(ln); -+ node_free_immediate(ln); - return ERR_PTR(-ENOMEM); - } - -@@ -857,7 +875,7 @@ add: - - rt->dst.rt6_next = iter; - *ins = rt; -- rt->rt6i_node = fn; -+ rcu_assign_pointer(rt->rt6i_node, fn); - atomic_inc(&rt->rt6i_ref); - inet6_rt_notify(RTM_NEWROUTE, rt, info, 0); - info->nl_net->ipv6.rt6_stats->fib_rt_entries++; -@@ -882,7 +900,7 @@ add: - return err; - - *ins = rt; -- rt->rt6i_node = fn; -+ rcu_assign_pointer(rt->rt6i_node, fn); - rt->dst.rt6_next = iter->dst.rt6_next; - atomic_inc(&rt->rt6i_ref); - inet6_rt_notify(RTM_NEWROUTE, rt, info, NLM_F_REPLACE); -@@ -1015,7 +1033,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, - root, and then (in failure) stale node - in main tree. - */ -- node_free(sfn); -+ node_free_immediate(sfn); - err = PTR_ERR(sn); - goto failure; - } -@@ -1442,8 +1460,9 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, - - int fib6_del(struct rt6_info *rt, struct nl_info *info) - { -+ struct fib6_node *fn = rcu_dereference_protected(rt->rt6i_node, -+ lockdep_is_held(&rt->rt6i_table->tb6_lock)); - struct net *net = info->nl_net; -- struct fib6_node *fn = rt->rt6i_node; - struct rt6_info **rtp; - - #if RT6_DEBUG >= 2 -@@ -1632,7 +1651,9 @@ static int fib6_clean_node(struct fib6_walker *w) - if (res) { - #if RT6_DEBUG >= 2 - pr_debug("%s: del failed: rt=%p@%p err=%d\n", -- __func__, rt, rt->rt6i_node, res); -+ __func__, rt, -+ rcu_access_pointer(rt->rt6i_node), -+ res); - #endif - continue; - } -@@ -1870,15 +1891,22 @@ out_timer: - - static void fib6_net_exit(struct net *net) - { -+ unsigned int i; -+ - rt6_ifdown(net, NULL); - del_timer_sync(&net->ipv6.ip6_fib_timer); - --#ifdef CONFIG_IPV6_MULTIPLE_TABLES -- inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers); -- kfree(net->ipv6.fib6_local_tbl); --#endif -- inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers); -- kfree(net->ipv6.fib6_main_tbl); -+ for (i = 0; i < FIB6_TABLE_HASHSZ; i++) { -+ struct hlist_head *head = &net->ipv6.fib_table_hash[i]; -+ struct hlist_node *tmp; -+ struct fib6_table *tb; -+ -+ hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) { -+ hlist_del(&tb->tb6_hlist); -+ fib6_free_table(tb); -+ } -+ } -+ - kfree(net->ipv6.fib_table_hash); - kfree(net->ipv6.rt6_stats); - } -diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c -index bab4441ed4e4..eb2dc39f7066 100644 ---- a/net/ipv6/netfilter/nf_conntrack_reasm.c -+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c -@@ -649,18 +649,12 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig); - - static int nf_ct_net_init(struct net *net) - { -- int res; -- - net->nf_frag.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; - net->nf_frag.frags.low_thresh = IPV6_FRAG_LOW_THRESH; - net->nf_frag.frags.timeout = IPV6_FRAG_TIMEOUT; -- res = inet_frags_init_net(&net->nf_frag.frags); -- if (res) -- return res; -- res = nf_ct_frag6_sysctl_register(net); -- if (res) -- inet_frags_uninit_net(&net->nf_frag.frags); -- return res; -+ inet_frags_init_net(&net->nf_frag.frags); -+ -+ return nf_ct_frag6_sysctl_register(net); - } - - static void nf_ct_net_exit(struct net *net) -diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c -index f9f02581c4ca..f99a04674419 100644 ---- a/net/ipv6/output_core.c -+++ b/net/ipv6/output_core.c -@@ -86,7 +86,6 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - - while (offset <= packet_len) { - struct ipv6_opt_hdr *exthdr; -- unsigned int len; - - switch (**nexthdr) { - -@@ -112,10 +111,9 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) - - exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + - offset); -- len = ipv6_optlen(exthdr); -- if (len + offset >= IPV6_MAXPLEN) -+ offset += ipv6_optlen(exthdr); -+ if (offset > IPV6_MAXPLEN) - return -EINVAL; -- offset += len; - *nexthdr = &exthdr->nexthdr; - } - -diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c -index a234552a7e3d..58f2139ebb5e 100644 ---- a/net/ipv6/reassembly.c -+++ b/net/ipv6/reassembly.c -@@ -708,19 +708,13 @@ static void ip6_frags_sysctl_unregister(void) - - static int __net_init ipv6_frags_init_net(struct net *net) - { -- int res; -- - net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; - net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; - net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; - -- res = inet_frags_init_net(&net->ipv6.frags); -- if (res) -- return res; -- res = ip6_frags_ns_sysctl_register(net); -- if (res) -- inet_frags_uninit_net(&net->ipv6.frags); -- return res; -+ inet_frags_init_net(&net->ipv6.frags); -+ -+ return ip6_frags_ns_sysctl_register(net); - } - - static void __net_exit ipv6_frags_exit_net(struct net *net) -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index ef335070e98a..48917437550e 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -1248,7 +1248,9 @@ static void rt6_dst_from_metrics_check(struct rt6_info *rt) - - static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie) - { -- if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) -+ u32 rt_cookie; -+ -+ if (!rt6_get_cookie_safe(rt, &rt_cookie) || rt_cookie != cookie) - return NULL; - - if (rt6_check_expired(rt)) -@@ -1316,8 +1318,14 @@ static void ip6_link_failure(struct sk_buff *skb) - if (rt->rt6i_flags & RTF_CACHE) { - dst_hold(&rt->dst); - ip6_del_rt(rt); -- } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { -- rt->rt6i_node->fn_sernum = -1; -+ } else { -+ struct fib6_node *fn; -+ -+ rcu_read_lock(); -+ fn = rcu_dereference(rt->rt6i_node); -+ if (fn && (rt->rt6i_flags & RTF_DEFAULT)) -+ fn->fn_sernum = -1; -+ rcu_read_unlock(); - } - } - } -@@ -1334,7 +1342,8 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu) - static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) - { - return !(rt->rt6i_flags & RTF_CACHE) && -- (rt->rt6i_flags & RTF_PCPU || rt->rt6i_node); -+ (rt->rt6i_flags & RTF_PCPU || -+ rcu_access_pointer(rt->rt6i_node)); - } - - static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.89-90.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.89-90.patch deleted file mode 100644 index 658420d3b..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.89-90.patch +++ /dev/null @@ -1,1208 +0,0 @@ -diff --git a/Makefile b/Makefile -index 7e4c46b375b3..ca5aaaf4aef7 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 89 -+SUBLEVEL = 90 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi -index 7f68a1ee7073..210192c38df3 100644 ---- a/arch/arm/boot/dts/pxa27x.dtsi -+++ b/arch/arm/boot/dts/pxa27x.dtsi -@@ -13,6 +13,7 @@ - interrupts = <25>; - #dma-channels = <32>; - #dma-cells = <2>; -+ #dma-requests = <75>; - status = "okay"; - }; - -diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi -index 564341af7e97..fec47bcd8292 100644 ---- a/arch/arm/boot/dts/pxa3xx.dtsi -+++ b/arch/arm/boot/dts/pxa3xx.dtsi -@@ -12,6 +12,7 @@ - interrupts = <25>; - #dma-channels = <32>; - #dma-cells = <2>; -+ #dma-requests = <100>; - status = "okay"; - }; - -diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c -index 2a6e0ae2b920..614e9d8f0a54 100644 ---- a/arch/arm/mach-pxa/devices.c -+++ b/arch/arm/mach-pxa/devices.c -@@ -1203,6 +1203,7 @@ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) - - static struct mmp_dma_platdata pxa_dma_pdata = { - .dma_channels = 0, -+ .nb_requestors = 0, - }; - - static struct resource pxa_dma_resource[] = { -@@ -1231,8 +1232,9 @@ static struct platform_device pxa2xx_pxa_dma = { - .resource = pxa_dma_resource, - }; - --void __init pxa2xx_set_dmac_info(int nb_channels) -+void __init pxa2xx_set_dmac_info(int nb_channels, int nb_requestors) - { - pxa_dma_pdata.dma_channels = nb_channels; -+ pxa_dma_pdata.nb_requestors = nb_requestors; - pxa_register_device(&pxa2xx_pxa_dma, &pxa_dma_pdata); - } -diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c -index 1dc85ffc3e20..049b9cc22720 100644 ---- a/arch/arm/mach-pxa/pxa25x.c -+++ b/arch/arm/mach-pxa/pxa25x.c -@@ -206,7 +206,7 @@ static int __init pxa25x_init(void) - register_syscore_ops(&pxa_irq_syscore_ops); - register_syscore_ops(&pxa2xx_mfp_syscore_ops); - -- pxa2xx_set_dmac_info(16); -+ pxa2xx_set_dmac_info(16, 40); - pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info); - ret = platform_add_devices(pxa25x_devices, - ARRAY_SIZE(pxa25x_devices)); -diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c -index ffc424028557..2fb6430b7a34 100644 ---- a/arch/arm/mach-pxa/pxa27x.c -+++ b/arch/arm/mach-pxa/pxa27x.c -@@ -309,7 +309,7 @@ static int __init pxa27x_init(void) - if (!of_have_populated_dt()) { - pxa_register_device(&pxa27x_device_gpio, - &pxa27x_gpio_info); -- pxa2xx_set_dmac_info(32); -+ pxa2xx_set_dmac_info(32, 75); - ret = platform_add_devices(devices, - ARRAY_SIZE(devices)); - } -diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c -index 20ce2d386f17..ca06f082497c 100644 ---- a/arch/arm/mach-pxa/pxa3xx.c -+++ b/arch/arm/mach-pxa/pxa3xx.c -@@ -450,7 +450,7 @@ static int __init pxa3xx_init(void) - if (of_have_populated_dt()) - return 0; - -- pxa2xx_set_dmac_info(32); -+ pxa2xx_set_dmac_info(32, 100); - ret = platform_add_devices(devices, ARRAY_SIZE(devices)); - if (ret) - return ret; -diff --git a/arch/arm/plat-pxa/include/plat/dma.h b/arch/arm/plat-pxa/include/plat/dma.h -index 28848b344e2d..ceba3e4184fc 100644 ---- a/arch/arm/plat-pxa/include/plat/dma.h -+++ b/arch/arm/plat-pxa/include/plat/dma.h -@@ -95,6 +95,6 @@ static inline int pxad_toggle_reserved_channel(int legacy_channel) - } - #endif - --extern void __init pxa2xx_set_dmac_info(int nb_channels); -+extern void __init pxa2xx_set_dmac_info(int nb_channels, int nb_requestors); - - #endif /* __PLAT_DMA_H */ -diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c -index c5f9a9e3d1f3..28d83f536e93 100644 ---- a/arch/arm/xen/mm.c -+++ b/arch/arm/xen/mm.c -@@ -199,6 +199,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { - .unmap_page = xen_swiotlb_unmap_page, - .dma_supported = xen_swiotlb_dma_supported, - .set_dma_mask = xen_swiotlb_set_dma_mask, -+ .mmap = xen_swiotlb_dma_mmap, - }; - - int __init xen_mm_init(void) -diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S -index 20ceb5edf7b8..d019c3a58cc2 100644 ---- a/arch/arm64/kernel/head.S -+++ b/arch/arm64/kernel/head.S -@@ -446,6 +446,7 @@ ENDPROC(__mmap_switched) - * booted in EL1 or EL2 respectively. - */ - ENTRY(el2_setup) -+ msr SPsel, #1 // We want to use SP_EL{1,2} - mrs x0, CurrentEL - cmp x0, #CurrentEL_EL2 - b.ne 1f -diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c -index 7fabf49f2aeb..86485415c5f0 100644 ---- a/arch/arm64/mm/fault.c -+++ b/arch/arm64/mm/fault.c -@@ -447,7 +447,7 @@ static struct fault_info { - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 0 translation fault" }, - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" }, - { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, -- { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, -+ { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, - { do_bad, SIGBUS, 0, "unknown 8" }, - { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, - { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, -diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c -index 54cf9bc94dad..3a095670b0c4 100644 ---- a/arch/powerpc/kvm/book3s_64_vio.c -+++ b/arch/powerpc/kvm/book3s_64_vio.c -@@ -101,22 +101,17 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, - struct kvm_create_spapr_tce *args) - { - struct kvmppc_spapr_tce_table *stt = NULL; -+ struct kvmppc_spapr_tce_table *siter; - long npages; - int ret = -ENOMEM; - int i; - -- /* Check this LIOBN hasn't been previously allocated */ -- list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { -- if (stt->liobn == args->liobn) -- return -EBUSY; -- } -- - npages = kvmppc_stt_npages(args->window_size); - - stt = kzalloc(sizeof(*stt) + npages * sizeof(struct page *), - GFP_KERNEL); - if (!stt) -- goto fail; -+ return ret; - - stt->liobn = args->liobn; - stt->window_size = args->window_size; -@@ -128,23 +123,36 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, - goto fail; - } - -- kvm_get_kvm(kvm); -- - mutex_lock(&kvm->lock); -- list_add(&stt->list, &kvm->arch.spapr_tce_tables); -+ -+ /* Check this LIOBN hasn't been previously allocated */ -+ ret = 0; -+ list_for_each_entry(siter, &kvm->arch.spapr_tce_tables, list) { -+ if (siter->liobn == args->liobn) { -+ ret = -EBUSY; -+ break; -+ } -+ } -+ -+ if (!ret) -+ ret = anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops, -+ stt, O_RDWR | O_CLOEXEC); -+ -+ if (ret >= 0) { -+ list_add(&stt->list, &kvm->arch.spapr_tce_tables); -+ kvm_get_kvm(kvm); -+ } - - mutex_unlock(&kvm->lock); - -- return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops, -- stt, O_RDWR | O_CLOEXEC); -+ if (ret >= 0) -+ return ret; - --fail: -- if (stt) { -- for (i = 0; i < npages; i++) -- if (stt->pages[i]) -- __free_page(stt->pages[i]); -+ fail: -+ for (i = 0; i < npages; i++) -+ if (stt->pages[i]) -+ __free_page(stt->pages[i]); - -- kfree(stt); -- } -+ kfree(stt); - return ret; - } -diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c -index ceb18d349459..8dd0c8edefd6 100644 ---- a/arch/powerpc/platforms/pseries/mobility.c -+++ b/arch/powerpc/platforms/pseries/mobility.c -@@ -225,8 +225,10 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) - return -ENOENT; - - dn = dlpar_configure_connector(drc_index, parent_dn); -- if (!dn) -+ if (!dn) { -+ of_node_put(parent_dn); - return -ENOENT; -+ } - - rc = dlpar_attach_node(dn); - if (rc) -diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c -index 0bc3490420c5..72a483c295f2 100644 ---- a/arch/x86/kernel/fpu/regset.c -+++ b/arch/x86/kernel/fpu/regset.c -@@ -116,6 +116,11 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, - xsave = &fpu->state.xsave; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); -+ -+ /* xcomp_bv must be 0 when using uncompacted format */ -+ if (!ret && xsave->header.xcomp_bv) -+ ret = -EINVAL; -+ - /* - * mxcsr reserved bits must be masked to zero for security reasons. - */ -@@ -126,6 +131,12 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, - */ - memset(&xsave->header.reserved, 0, 48); - -+ /* -+ * In case of failure, mark all states as init: -+ */ -+ if (ret) -+ fpstate_init(&fpu->state); -+ - return ret; - } - -diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c -index 31c6a60505e6..3de077116218 100644 ---- a/arch/x86/kernel/fpu/signal.c -+++ b/arch/x86/kernel/fpu/signal.c -@@ -309,7 +309,9 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) - fpu__drop(fpu); - - if (__copy_from_user(&fpu->state.xsave, buf_fx, state_size) || -- __copy_from_user(&env, buf, sizeof(env))) { -+ __copy_from_user(&env, buf, sizeof(env)) || -+ (state_size > offsetof(struct xregs_state, header) && -+ fpu->state.xsave.header.xcomp_bv)) { - fpstate_init(&fpu->state); - err = -1; - } else { -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index b12391119ce8..a018dff00808 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -2029,8 +2029,8 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu) - - /* Allow posting non-urgent interrupts */ - new.sn = 0; -- } while (cmpxchg(&pi_desc->control, old.control, -- new.control) != old.control); -+ } while (cmpxchg64(&pi_desc->control, old.control, -+ new.control) != old.control); - } - /* - * Switches to specified vcpu, until a matching vcpu_put(), but assumes -@@ -4541,21 +4541,30 @@ static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu) - { - #ifdef CONFIG_SMP - if (vcpu->mode == IN_GUEST_MODE) { -- struct vcpu_vmx *vmx = to_vmx(vcpu); -- - /* -- * Currently, we don't support urgent interrupt, -- * all interrupts are recognized as non-urgent -- * interrupt, so we cannot post interrupts when -- * 'SN' is set. -+ * The vector of interrupt to be delivered to vcpu had -+ * been set in PIR before this function. -+ * -+ * Following cases will be reached in this block, and -+ * we always send a notification event in all cases as -+ * explained below. - * -- * If the vcpu is in guest mode, it means it is -- * running instead of being scheduled out and -- * waiting in the run queue, and that's the only -- * case when 'SN' is set currently, warning if -- * 'SN' is set. -+ * Case 1: vcpu keeps in non-root mode. Sending a -+ * notification event posts the interrupt to vcpu. -+ * -+ * Case 2: vcpu exits to root mode and is still -+ * runnable. PIR will be synced to vIRR before the -+ * next vcpu entry. Sending a notification event in -+ * this case has no effect, as vcpu is not in root -+ * mode. -+ * -+ * Case 3: vcpu exits to root mode and is blocked. -+ * vcpu_block() has already synced PIR to vIRR and -+ * never blocks vcpu if vIRR is not cleared. Therefore, -+ * a blocked vcpu here does not wait for any requested -+ * interrupts in PIR, and sending a notification event -+ * which has no effect is safe here. - */ -- WARN_ON_ONCE(pi_test_sn(&vmx->pi_desc)); - - apic->send_IPI_mask(get_cpu_mask(vcpu->cpu), - POSTED_INTR_VECTOR); -@@ -9683,6 +9692,11 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) - vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, - page_to_phys(vmx->nested.virtual_apic_page)); - vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold); -+ } else { -+#ifdef CONFIG_X86_64 -+ exec_control |= CPU_BASED_CR8_LOAD_EXITING | -+ CPU_BASED_CR8_STORE_EXITING; -+#endif - } - - if (cpu_has_vmx_msr_bitmap() && -@@ -10691,8 +10705,8 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu) - - /* set 'NV' to 'wakeup vector' */ - new.nv = POSTED_INTR_WAKEUP_VECTOR; -- } while (cmpxchg(&pi_desc->control, old.control, -- new.control) != old.control); -+ } while (cmpxchg64(&pi_desc->control, old.control, -+ new.control) != old.control); - - return 0; - } -@@ -10723,8 +10737,8 @@ static void vmx_post_block(struct kvm_vcpu *vcpu) - - /* set 'NV' to 'notification vector' */ - new.nv = POSTED_INTR_VECTOR; -- } while (cmpxchg(&pi_desc->control, old.control, -- new.control) != old.control); -+ } while (cmpxchg64(&pi_desc->control, old.control, -+ new.control) != old.control); - - if(vcpu->pre_pcpu != -1) { - spin_lock_irqsave( -@@ -10755,7 +10769,7 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, - struct kvm_lapic_irq irq; - struct kvm_vcpu *vcpu; - struct vcpu_data vcpu_info; -- int idx, ret = -EINVAL; -+ int idx, ret = 0; - - if (!kvm_arch_has_assigned_device(kvm) || - !irq_remapping_cap(IRQ_POSTING_CAP)) -@@ -10763,7 +10777,12 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, - - idx = srcu_read_lock(&kvm->irq_srcu); - irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- BUG_ON(guest_irq >= irq_rt->nr_rt_entries); -+ if (guest_irq >= irq_rt->nr_rt_entries || -+ hlist_empty(&irq_rt->map[guest_irq])) { -+ pr_warn_once("no route for guest_irq %u/%u (broken user space?)\n", -+ guest_irq, irq_rt->nr_rt_entries); -+ goto out; -+ } - - hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) { - if (e->type != KVM_IRQ_ROUTING_MSI) -@@ -10793,12 +10812,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq, - - if (set) - ret = irq_set_vcpu_affinity(host_irq, &vcpu_info); -- else { -- /* suppress notification event before unposting */ -- pi_set_sn(vcpu_to_pi_desc(vcpu)); -+ else - ret = irq_set_vcpu_affinity(host_irq, NULL); -- pi_clear_sn(vcpu_to_pi_desc(vcpu)); -- } - - if (ret < 0) { - printk(KERN_INFO "%s: failed to update PI IRTE\n", -diff --git a/block/bsg-lib.c b/block/bsg-lib.c -index 650f427d915b..341b8d858e67 100644 ---- a/block/bsg-lib.c -+++ b/block/bsg-lib.c -@@ -147,7 +147,6 @@ static int bsg_create_job(struct device *dev, struct request *req) - failjob_rls_rqst_payload: - kfree(job->request_payload.sg_list); - failjob_rls_job: -- kfree(job); - return -ENOMEM; - } - -diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c -index 6a60936b46e0..62ce93568e11 100644 ---- a/drivers/crypto/talitos.c -+++ b/drivers/crypto/talitos.c -@@ -1749,9 +1749,9 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, - req_ctx->swinit = 0; - } else { - desc->ptr[1] = zero_entry; -- /* Indicate next op is not the first. */ -- req_ctx->first = 0; - } -+ /* Indicate next op is not the first. */ -+ req_ctx->first = 0; - - /* HMAC key */ - if (ctx->keylen) -@@ -2770,7 +2770,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, - t_alg->algt.alg.hash.final = ahash_final; - t_alg->algt.alg.hash.finup = ahash_finup; - t_alg->algt.alg.hash.digest = ahash_digest; -- t_alg->algt.alg.hash.setkey = ahash_setkey; -+ if (!strncmp(alg->cra_name, "hmac", 4)) -+ t_alg->algt.alg.hash.setkey = ahash_setkey; - t_alg->algt.alg.hash.import = ahash_import; - t_alg->algt.alg.hash.export = ahash_export; - -diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c -index 5eac08ffc697..d55bf85b76ce 100644 ---- a/drivers/md/raid5.c -+++ b/drivers/md/raid5.c -@@ -818,6 +818,14 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh - spin_unlock(&head->batch_head->batch_lock); - goto unlock_out; - } -+ /* -+ * We must assign batch_head of this stripe within the -+ * batch_lock, otherwise clear_batch_ready of batch head -+ * stripe could clear BATCH_READY bit of this stripe and -+ * this stripe->batch_head doesn't get assigned, which -+ * could confuse clear_batch_ready for this stripe -+ */ -+ sh->batch_head = head->batch_head; - - /* - * at this point, head's BATCH_READY could be cleared, but we -@@ -825,8 +833,6 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh - */ - list_add(&sh->batch_list, &head->batch_list); - spin_unlock(&head->batch_head->batch_lock); -- -- sh->batch_head = head->batch_head; - } else { - head->batch_head = head; - sh->batch_head = head->batch_head; -@@ -4258,7 +4264,8 @@ static void break_stripe_batch_list(struct stripe_head *head_sh, - - set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS | - (1 << STRIPE_PREREAD_ACTIVE) | -- (1 << STRIPE_DEGRADED)), -+ (1 << STRIPE_DEGRADED) | -+ (1 << STRIPE_ON_UNPLUG_LIST)), - head_sh->state & (1 << STRIPE_INSYNC)); - - sh->check_state = head_sh->check_state; -diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c -index ea3eeb7011e1..690eb1a18caf 100644 ---- a/drivers/misc/cxl/api.c -+++ b/drivers/misc/cxl/api.c -@@ -176,6 +176,10 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, - kernel = false; - } - -+ /* -+ * Increment driver use count. Enables global TLBIs for hash -+ * and callbacks to handle the segment table -+ */ - cxl_ctx_get(); - - if ((rc = cxl_attach_process(ctx, kernel, wed , 0))) { -diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c -index 10a02934bfc0..013558f4da4f 100644 ---- a/drivers/misc/cxl/file.c -+++ b/drivers/misc/cxl/file.c -@@ -94,7 +94,6 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) - - pr_devel("afu_open pe: %i\n", ctx->pe); - file->private_data = ctx; -- cxl_ctx_get(); - - /* indicate success */ - rc = 0; -@@ -205,11 +204,18 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, - ctx->pid = get_task_pid(current, PIDTYPE_PID); - ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID); - -+ /* -+ * Increment driver use count. Enables global TLBIs for hash -+ * and callbacks to handle the segment table -+ */ -+ cxl_ctx_get(); -+ - trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); - - if ((rc = cxl_attach_process(ctx, false, work.work_element_descriptor, - amr))) { - afu_release_irqs(ctx, ctx); -+ cxl_ctx_put(); - goto out; - } - -diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c -index f8b2b5987ea9..ec91cd17bf34 100644 ---- a/drivers/pci/pci-sysfs.c -+++ b/drivers/pci/pci-sysfs.c -@@ -522,7 +522,7 @@ static ssize_t driver_override_store(struct device *dev, - const char *buf, size_t count) - { - struct pci_dev *pdev = to_pci_dev(dev); -- char *driver_override, *old = pdev->driver_override, *cp; -+ char *driver_override, *old, *cp; - - /* We need to keep extra room for a newline */ - if (count >= (PAGE_SIZE - 1)) -@@ -536,12 +536,15 @@ static ssize_t driver_override_store(struct device *dev, - if (cp) - *cp = '\0'; - -+ device_lock(dev); -+ old = pdev->driver_override; - if (strlen(driver_override)) { - pdev->driver_override = driver_override; - } else { - kfree(driver_override); - pdev->driver_override = NULL; - } -+ device_unlock(dev); - - kfree(old); - -@@ -552,8 +555,12 @@ static ssize_t driver_override_show(struct device *dev, - struct device_attribute *attr, char *buf) - { - struct pci_dev *pdev = to_pci_dev(dev); -+ ssize_t len; - -- return snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); -+ device_lock(dev); -+ len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); -+ device_unlock(dev); -+ return len; - } - static DEVICE_ATTR_RW(driver_override); - -diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c -index e4b3d8f4fd85..bb4ed7b1f5df 100644 ---- a/drivers/scsi/scsi_transport_iscsi.c -+++ b/drivers/scsi/scsi_transport_iscsi.c -@@ -3697,7 +3697,7 @@ iscsi_if_rx(struct sk_buff *skb) - uint32_t group; - - nlh = nlmsg_hdr(skb); -- if (nlh->nlmsg_len < sizeof(*nlh) || -+ if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) || - skb->len < nlh->nlmsg_len) { - break; - } -diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c -index f34ed47fcaf8..7f658fa4d22a 100644 ---- a/drivers/video/fbdev/aty/atyfb_base.c -+++ b/drivers/video/fbdev/aty/atyfb_base.c -@@ -1861,7 +1861,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) - #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) - case ATYIO_CLKR: - if (M64_HAS(INTEGRATED)) { -- struct atyclk clk; -+ struct atyclk clk = { 0 }; - union aty_pll *pll = &par->pll; - u32 dsp_config = pll->ct.dsp_config; - u32 dsp_on_off = pll->ct.dsp_on_off; -diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c -index 8a58bbc14de2..f7b19c25c3a4 100644 ---- a/drivers/xen/swiotlb-xen.c -+++ b/drivers/xen/swiotlb-xen.c -@@ -680,3 +680,22 @@ xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask) - return 0; - } - EXPORT_SYMBOL_GPL(xen_swiotlb_set_dma_mask); -+ -+/* -+ * Create userspace mapping for the DMA-coherent memory. -+ * This function should be called with the pages from the current domain only, -+ * passing pages mapped from other domains would lead to memory corruption. -+ */ -+int -+xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size, -+ struct dma_attrs *attrs) -+{ -+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) -+ if (__generic_dma_ops(dev)->mmap) -+ return __generic_dma_ops(dev)->mmap(dev, vma, cpu_addr, -+ dma_addr, size, attrs); -+#endif -+ return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); -+} -+EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mmap); -diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c -index 317b99acdf4b..9c3b9d07f341 100644 ---- a/fs/btrfs/ioctl.c -+++ b/fs/btrfs/ioctl.c -@@ -2984,7 +2984,7 @@ static int btrfs_cmp_data_prepare(struct inode *src, u64 loff, - out: - if (ret) - btrfs_cmp_data_free(cmp); -- return 0; -+ return ret; - } - - static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, -@@ -4118,6 +4118,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) - ret = PTR_ERR(new_root); - goto out; - } -+ if (!is_fstree(new_root->objectid)) { -+ ret = -ENOENT; -+ goto out; -+ } - - path = btrfs_alloc_path(); - if (!path) { -diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c -index 8ca9aa92972d..9ebe027cc4b7 100644 ---- a/fs/btrfs/relocation.c -+++ b/fs/btrfs/relocation.c -@@ -2350,11 +2350,11 @@ void free_reloc_roots(struct list_head *list) - while (!list_empty(list)) { - reloc_root = list_entry(list->next, struct btrfs_root, - root_list); -+ __del_reloc_root(reloc_root); - free_extent_buffer(reloc_root->node); - free_extent_buffer(reloc_root->commit_root); - reloc_root->node = NULL; - reloc_root->commit_root = NULL; -- __del_reloc_root(reloc_root); - } - } - -diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c -index 53a827c6d8b1..b377aa8f266f 100644 ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -4060,6 +4060,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, - cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", - server->sec_mode, server->capabilities, server->timeAdj); - -+ if (ses->auth_key.response) { -+ cifs_dbg(VFS, "Free previous auth_key.response = %p\n", -+ ses->auth_key.response); -+ kfree(ses->auth_key.response); -+ ses->auth_key.response = NULL; -+ ses->auth_key.len = 0; -+ } -+ - if (server->ops->sess_setup) - rc = server->ops->sess_setup(xid, ses, nls_info); - -diff --git a/fs/cifs/file.c b/fs/cifs/file.c -index a0c0a49b6620..ec2d07bb9beb 100644 ---- a/fs/cifs/file.c -+++ b/fs/cifs/file.c -@@ -224,6 +224,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - -+ /* O_SYNC also has bit for O_DSYNC so following check picks up either */ -+ if (f_flags & O_SYNC) -+ create_options |= CREATE_WRITE_THROUGH; -+ -+ if (f_flags & O_DIRECT) -+ create_options |= CREATE_NO_BUFFER; -+ - oparms.tcon = tcon; - oparms.cifs_sb = cifs_sb; - oparms.desired_access = desired_access; -diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c -index 6c484ddf26a9..f2ff60e58ec8 100644 ---- a/fs/cifs/smb2pdu.c -+++ b/fs/cifs/smb2pdu.c -@@ -361,7 +361,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req) - build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); - req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); - req->NegotiateContextCount = cpu_to_le16(2); -- inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) + 2 -+ inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) - + sizeof(struct smb2_encryption_neg_context)); /* calculate hash */ - } - #else -@@ -526,15 +526,22 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) - - /* - * validation ioctl must be signed, so no point sending this if we -- * can not sign it. We could eventually change this to selectively -+ * can not sign it (ie are not known user). Even if signing is not -+ * required (enabled but not negotiated), in those cases we selectively - * sign just this, the first and only signed request on a connection. -- * This is good enough for now since a user who wants better security -- * would also enable signing on the mount. Having validation of -- * negotiate info for signed connections helps reduce attack vectors -+ * Having validation of negotiate info helps reduce attack vectors. - */ -- if (tcon->ses->server->sign == false) -+ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) - return 0; /* validation requires signing */ - -+ if (tcon->ses->user_name == NULL) { -+ cifs_dbg(FYI, "Can't validate negotiate: null user mount\n"); -+ return 0; /* validation requires signing */ -+ } -+ -+ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) -+ cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); -+ - vneg_inbuf.Capabilities = - cpu_to_le32(tcon->ses->server->vals->req_capabilities); - memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid, -diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c -index 070901e76653..ff36f5475d7e 100644 ---- a/fs/gfs2/glock.c -+++ b/fs/gfs2/glock.c -@@ -1814,13 +1814,10 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) - { - struct gfs2_glock_iter *gi = seq->private; - loff_t n = *pos; -- int ret; -- -- if (gi->last_pos <= *pos) -- n = (*pos - gi->last_pos); - -- ret = rhashtable_walk_start(&gi->hti); -- if (ret) -+ if (rhashtable_walk_init(&gl_hash_table, &gi->hti) != 0) -+ return NULL; -+ if (rhashtable_walk_start(&gi->hti) != 0) - return NULL; - - do { -@@ -1828,6 +1825,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) - } while (gi->gl && n--); - - gi->last_pos = *pos; -+ - return gi->gl; - } - -@@ -1839,6 +1837,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, - (*pos)++; - gi->last_pos = *pos; - gfs2_glock_iter_next(gi); -+ - return gi->gl; - } - -@@ -1847,7 +1846,10 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr) - struct gfs2_glock_iter *gi = seq->private; - - gi->gl = NULL; -- rhashtable_walk_stop(&gi->hti); -+ if (gi->hti.walker) { -+ rhashtable_walk_stop(&gi->hti); -+ rhashtable_walk_exit(&gi->hti); -+ } - } - - static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) -@@ -1910,12 +1912,10 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) - struct gfs2_glock_iter *gi = seq->private; - - gi->sdp = inode->i_private; -- gi->last_pos = 0; - seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); - if (seq->buf) - seq->size = GFS2_SEQ_GOODSIZE; - gi->gl = NULL; -- ret = rhashtable_walk_init(&gl_hash_table, &gi->hti); - } - return ret; - } -@@ -1926,7 +1926,6 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file) - struct gfs2_glock_iter *gi = seq->private; - - gi->gl = NULL; -- rhashtable_walk_exit(&gi->hti); - return seq_release_private(inode, file); - } - -@@ -1938,12 +1937,10 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) - struct seq_file *seq = file->private_data; - struct gfs2_glock_iter *gi = seq->private; - gi->sdp = inode->i_private; -- gi->last_pos = 0; - seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); - if (seq->buf) - seq->size = GFS2_SEQ_GOODSIZE; - gi->gl = NULL; -- ret = rhashtable_walk_init(&gl_hash_table, &gi->hti); - } - return ret; - } -diff --git a/fs/read_write.c b/fs/read_write.c -index 819ef3faf1bb..bfd1a5dddf6e 100644 ---- a/fs/read_write.c -+++ b/fs/read_write.c -@@ -112,7 +112,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence, - * In the generic case the entire file is data, so as long as - * offset isn't at the end of the file then the offset is data. - */ -- if (offset >= eof) -+ if ((unsigned long long)offset >= eof) - return -ENXIO; - break; - case SEEK_HOLE: -@@ -120,7 +120,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence, - * There is a virtual hole at the end of the file, so as long as - * offset isn't i_size or larger, return i_size. - */ -- if (offset >= eof) -+ if ((unsigned long long)offset >= eof) - return -ENXIO; - offset = eof; - break; -diff --git a/include/linux/key.h b/include/linux/key.h -index 66f705243985..dcc115e8dd03 100644 ---- a/include/linux/key.h -+++ b/include/linux/key.h -@@ -177,6 +177,7 @@ struct key { - #define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ - #define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ - #define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ -+#define KEY_FLAG_UID_KEYRING 12 /* set if key is a user or user session keyring */ - - /* the key type and key description string - * - the desc is used to match a key against search criteria -@@ -218,6 +219,7 @@ extern struct key *key_alloc(struct key_type *type, - #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ - #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ - #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ -+#define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ - - extern void key_revoke(struct key *key); - extern void key_invalidate(struct key *key); -diff --git a/include/linux/platform_data/mmp_dma.h b/include/linux/platform_data/mmp_dma.h -index 2a330ec9e2af..d1397c8ed94e 100644 ---- a/include/linux/platform_data/mmp_dma.h -+++ b/include/linux/platform_data/mmp_dma.h -@@ -14,6 +14,7 @@ - - struct mmp_dma_platdata { - int dma_channels; -+ int nb_requestors; - }; - - #endif /* MMP_DMA_H */ -diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h -index 8b2eb93ae8ba..4d7fdbf20eff 100644 ---- a/include/xen/swiotlb-xen.h -+++ b/include/xen/swiotlb-xen.h -@@ -58,4 +58,9 @@ xen_swiotlb_dma_supported(struct device *hwdev, u64 mask); - - extern int - xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask); -+ -+extern int -+xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size, -+ struct dma_attrs *attrs); - #endif /* __LINUX_SWIOTLB_XEN_H */ -diff --git a/kernel/seccomp.c b/kernel/seccomp.c -index 15a1795bbba1..efd384f3f852 100644 ---- a/kernel/seccomp.c -+++ b/kernel/seccomp.c -@@ -457,14 +457,19 @@ static long seccomp_attach_filter(unsigned int flags, - return 0; - } - -+void __get_seccomp_filter(struct seccomp_filter *filter) -+{ -+ /* Reference count is bounded by the number of total processes. */ -+ atomic_inc(&filter->usage); -+} -+ - /* get_seccomp_filter - increments the reference count of the filter on @tsk */ - void get_seccomp_filter(struct task_struct *tsk) - { - struct seccomp_filter *orig = tsk->seccomp.filter; - if (!orig) - return; -- /* Reference count is bounded by the number of total processes. */ -- atomic_inc(&orig->usage); -+ __get_seccomp_filter(orig); - } - - static inline void seccomp_filter_free(struct seccomp_filter *filter) -@@ -475,10 +480,8 @@ static inline void seccomp_filter_free(struct seccomp_filter *filter) - } - } - --/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */ --void put_seccomp_filter(struct task_struct *tsk) -+static void __put_seccomp_filter(struct seccomp_filter *orig) - { -- struct seccomp_filter *orig = tsk->seccomp.filter; - /* Clean up single-reference branches iteratively. */ - while (orig && atomic_dec_and_test(&orig->usage)) { - struct seccomp_filter *freeme = orig; -@@ -487,6 +490,12 @@ void put_seccomp_filter(struct task_struct *tsk) - } - } - -+/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */ -+void put_seccomp_filter(struct task_struct *tsk) -+{ -+ __put_seccomp_filter(tsk->seccomp.filter); -+} -+ - /** - * seccomp_send_sigsys - signals the task to allow in-process syscall emulation - * @syscall: syscall number to send to userland -@@ -927,13 +936,13 @@ long seccomp_get_filter(struct task_struct *task, unsigned long filter_off, - if (!data) - goto out; - -- get_seccomp_filter(task); -+ __get_seccomp_filter(filter); - spin_unlock_irq(&task->sighand->siglock); - - if (copy_to_user(data, fprog->filter, bpf_classic_proglen(fprog))) - ret = -EFAULT; - -- put_seccomp_filter(task); -+ __put_seccomp_filter(filter); - return ret; - - out: -diff --git a/kernel/sysctl.c b/kernel/sysctl.c -index 002ec084124b..17c59e78661b 100644 ---- a/kernel/sysctl.c -+++ b/kernel/sysctl.c -@@ -1159,6 +1159,8 @@ static struct ctl_table kern_table[] = { - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = timer_migration_handler, -+ .extra1 = &zero, -+ .extra2 = &one, - }, - #endif - #ifdef CONFIG_BPF_SYSCALL -diff --git a/kernel/time/timer.c b/kernel/time/timer.c -index bbc5d1114583..125407144c01 100644 ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -127,7 +127,7 @@ int timer_migration_handler(struct ctl_table *table, int write, - int ret; - - mutex_lock(&mutex); -- ret = proc_dointvec(table, write, buffer, lenp, ppos); -+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); - if (!ret && write) - timers_update_migration(false); - mutex_unlock(&mutex); -diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index 4743066010c4..b64f35afee4e 100644 ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -3226,11 +3226,17 @@ static int tracing_open(struct inode *inode, struct file *file) - /* If this file was open for write, then erase contents */ - if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { - int cpu = tracing_get_cpu(inode); -+ struct trace_buffer *trace_buf = &tr->trace_buffer; -+ -+#ifdef CONFIG_TRACER_MAX_TRACE -+ if (tr->current_trace->print_max) -+ trace_buf = &tr->max_buffer; -+#endif - - if (cpu == RING_BUFFER_ALL_CPUS) -- tracing_reset_online_cpus(&tr->trace_buffer); -+ tracing_reset_online_cpus(trace_buf); - else -- tracing_reset(&tr->trace_buffer, cpu); -+ tracing_reset(trace_buf, cpu); - } - - if (file->f_mode & FMODE_READ) { -@@ -4701,7 +4707,7 @@ static int tracing_wait_pipe(struct file *filp) - * - * iter->pos will be 0 if we haven't read anything. - */ -- if (!tracing_is_on() && iter->pos) -+ if (!tracer_tracing_is_on(iter->tr) && iter->pos) - break; - - mutex_unlock(&iter->mutex); -diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c -index 04401037140e..b6be51940ead 100644 ---- a/net/mac80211/offchannel.c -+++ b/net/mac80211/offchannel.c -@@ -469,6 +469,8 @@ void ieee80211_roc_purge(struct ieee80211_local *local, - struct ieee80211_roc_work *roc, *tmp; - LIST_HEAD(tmp_list); - -+ flush_work(&local->hw_roc_start); -+ - mutex_lock(&local->mtx); - list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { - if (sdata && roc->sdata != sdata) -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index de10e3c0e2a4..8ece212aa3d2 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -9786,6 +9786,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) - if (err) - return err; - -+ if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] || -+ !tb[NL80211_REKEY_DATA_KCK]) -+ return -EINVAL; - if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) - return -ERANGE; - if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) -diff --git a/security/keys/internal.h b/security/keys/internal.h -index 5105c2c2da75..51ffb9cde073 100644 ---- a/security/keys/internal.h -+++ b/security/keys/internal.h -@@ -136,7 +136,7 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, - extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx); - extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx); - --extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); -+extern struct key *find_keyring_by_name(const char *name, bool uid_keyring); - - extern int install_user_keyrings(void); - extern int install_thread_keyring_to_cred(struct cred *); -diff --git a/security/keys/key.c b/security/keys/key.c -index 09c10b181881..51d23c623424 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, - key->flags |= 1 << KEY_FLAG_IN_QUOTA; - if (flags & KEY_ALLOC_TRUSTED) - key->flags |= 1 << KEY_FLAG_TRUSTED; -+ if (flags & KEY_ALLOC_UID_KEYRING) -+ key->flags |= 1 << KEY_FLAG_UID_KEYRING; - - #ifdef KEY_DEBUGGING - key->magic = KEY_DEBUG_MAGIC; -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index 671709d8610d..a009dc66eb8f 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -738,6 +738,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) - - key = key_ref_to_ptr(key_ref); - -+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { -+ ret = -ENOKEY; -+ goto error2; -+ } -+ - /* see if we can read it directly */ - ret = key_permission(key_ref, KEY_NEED_READ); - if (ret == 0) -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index f931ccfeefb0..0c8dd4fbe130 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -416,7 +416,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) - } - - struct keyring_read_iterator_context { -- size_t qty; -+ size_t buflen; - size_t count; - key_serial_t __user *buffer; - }; -@@ -428,9 +428,9 @@ static int keyring_read_iterator(const void *object, void *data) - int ret; - - kenter("{%s,%d},,{%zu/%zu}", -- key->type->name, key->serial, ctx->count, ctx->qty); -+ key->type->name, key->serial, ctx->count, ctx->buflen); - -- if (ctx->count >= ctx->qty) -+ if (ctx->count >= ctx->buflen) - return 1; - - ret = put_user(key->serial, ctx->buffer); -@@ -465,16 +465,12 @@ static long keyring_read(const struct key *keyring, - return 0; - - /* Calculate how much data we could return */ -- ctx.qty = nr_keys * sizeof(key_serial_t); -- - if (!buffer || !buflen) -- return ctx.qty; -- -- if (buflen > ctx.qty) -- ctx.qty = buflen; -+ return nr_keys * sizeof(key_serial_t); - - /* Copy the IDs of the subscribed keys into the buffer */ - ctx.buffer = (key_serial_t __user *)buffer; -+ ctx.buflen = buflen; - ctx.count = 0; - ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); - if (ret < 0) { -@@ -965,15 +961,15 @@ found: - /* - * Find a keyring with the specified name. - * -- * All named keyrings in the current user namespace are searched, provided they -- * grant Search permission directly to the caller (unless this check is -- * skipped). Keyrings whose usage points have reached zero or who have been -- * revoked are skipped. -+ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a -+ * user in the current user namespace are considered. If @uid_keyring is %true, -+ * the keyring additionally must have been allocated as a user or user session -+ * keyring; otherwise, it must grant Search permission directly to the caller. - * - * Returns a pointer to the keyring with the keyring's refcount having being - * incremented on success. -ENOKEY is returned if a key could not be found. - */ --struct key *find_keyring_by_name(const char *name, bool skip_perm_check) -+struct key *find_keyring_by_name(const char *name, bool uid_keyring) - { - struct key *keyring; - int bucket; -@@ -1001,10 +997,15 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) - if (strcmp(keyring->description, name) != 0) - continue; - -- if (!skip_perm_check && -- key_permission(make_key_ref(keyring, 0), -- KEY_NEED_SEARCH) < 0) -- continue; -+ if (uid_keyring) { -+ if (!test_bit(KEY_FLAG_UID_KEYRING, -+ &keyring->flags)) -+ continue; -+ } else { -+ if (key_permission(make_key_ref(keyring, 0), -+ KEY_NEED_SEARCH) < 0) -+ continue; -+ } - - /* we've got a match but we might end up racing with - * key_cleanup() if the keyring is currently 'dead' -diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index 4ed909142956..7dd050f24261 100644 ---- a/security/keys/process_keys.c -+++ b/security/keys/process_keys.c -@@ -76,7 +76,9 @@ int install_user_keyrings(void) - if (IS_ERR(uid_keyring)) { - uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, - cred, user_keyring_perm, -- KEY_ALLOC_IN_QUOTA, NULL); -+ KEY_ALLOC_UID_KEYRING | -+ KEY_ALLOC_IN_QUOTA, -+ NULL); - if (IS_ERR(uid_keyring)) { - ret = PTR_ERR(uid_keyring); - goto error; -@@ -92,7 +94,9 @@ int install_user_keyrings(void) - session_keyring = - keyring_alloc(buf, user->uid, INVALID_GID, - cred, user_keyring_perm, -- KEY_ALLOC_IN_QUOTA, NULL); -+ KEY_ALLOC_UID_KEYRING | -+ KEY_ALLOC_IN_QUOTA, -+ NULL); - if (IS_ERR(session_keyring)) { - ret = PTR_ERR(session_keyring); - goto error_release; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.90-91.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.90-91.patch deleted file mode 100644 index 65a73f3ae..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.90-91.patch +++ /dev/null @@ -1,2284 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt -new file mode 100644 -index 000000000000..6ec1a880ac18 ---- /dev/null -+++ b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt -@@ -0,0 +1,46 @@ -+THS8135 Video DAC -+----------------- -+ -+This is the binding for Texas Instruments THS8135 Video DAC bridge. -+ -+Required properties: -+ -+- compatible: Must be "ti,ths8135" -+ -+Required nodes: -+ -+This device has two video ports. Their connections are modelled using the OF -+graph bindings specified in Documentation/devicetree/bindings/graph.txt. -+ -+- Video port 0 for RGB input -+- Video port 1 for VGA output -+ -+Example -+------- -+ -+vga-bridge { -+ compatible = "ti,ths8135"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ -+ vga_bridge_in: endpoint { -+ remote-endpoint = <&lcdc_out_vga>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ -+ vga_bridge_out: endpoint { -+ remote-endpoint = <&vga_con_in>; -+ }; -+ }; -+ }; -+}; -diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt -new file mode 100644 -index 000000000000..b3629405f568 ---- /dev/null -+++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt -@@ -0,0 +1,18 @@ -+* AVIA HX711 ADC chip for weight cells -+ Bit-banging driver -+ -+Required properties: -+ - compatible: Should be "avia,hx711" -+ - sck-gpios: Definition of the GPIO for the clock -+ - dout-gpios: Definition of the GPIO for data-out -+ See Documentation/devicetree/bindings/gpio/gpio.txt -+ - avdd-supply: Definition of the regulator used as analog supply -+ -+Example: -+weight@0 { -+ compatible = "avia,hx711"; -+ sck-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; -+ dout-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; -+ avdd-suppy = <&avdd>; -+}; -+ -diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt -index 55df1d444e9f..98dc17507a84 100644 ---- a/Documentation/devicetree/bindings/vendor-prefixes.txt -+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -31,6 +31,7 @@ asahi-kasei Asahi Kasei Corp. - atmel Atmel Corporation - auo AU Optronics Corporation - avago Avago Technologies -+avia avia semiconductor - avic Shanghai AVIC Optoelectronics Co., Ltd. - axis Axis Communications AB - bosch Bosch Sensortec GmbH -diff --git a/Makefile b/Makefile -index ca5aaaf4aef7..c1db50ef7fb5 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 90 -+SUBLEVEL = 91 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu -index aed66d5df7f1..b7576349528c 100644 ---- a/arch/arm/Kconfig-nommu -+++ b/arch/arm/Kconfig-nommu -@@ -34,8 +34,7 @@ config PROCESSOR_ID - used instead of the auto-probing which utilizes the register. - - config REMAP_VECTORS_TO_RAM -- bool 'Install vectors to the beginning of RAM' if DRAM_BASE -- depends on DRAM_BASE -+ bool 'Install vectors to the beginning of RAM' - help - The kernel needs to change the hardware exception vectors. - In nommu mode, the hardware exception vectors are normally -diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi -index e07ae5d45e19..7b39d8fae61e 100644 ---- a/arch/arm/boot/dts/r8a7790.dtsi -+++ b/arch/arm/boot/dts/r8a7790.dtsi -@@ -1409,7 +1409,8 @@ - }; - - msiof0: spi@e6e20000 { -- compatible = "renesas,msiof-r8a7790"; -+ compatible = "renesas,msiof-r8a7790", -+ "renesas,rcar-gen2-msiof"; - reg = <0 0xe6e20000 0 0x0064>; - interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>; -@@ -1422,7 +1423,8 @@ - }; - - msiof1: spi@e6e10000 { -- compatible = "renesas,msiof-r8a7790"; -+ compatible = "renesas,msiof-r8a7790", -+ "renesas,rcar-gen2-msiof"; - reg = <0 0xe6e10000 0 0x0064>; - interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>; -@@ -1435,7 +1437,8 @@ - }; - - msiof2: spi@e6e00000 { -- compatible = "renesas,msiof-r8a7790"; -+ compatible = "renesas,msiof-r8a7790", -+ "renesas,rcar-gen2-msiof"; - reg = <0 0xe6e00000 0 0x0064>; - interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>; -@@ -1448,7 +1451,8 @@ - }; - - msiof3: spi@e6c90000 { -- compatible = "renesas,msiof-r8a7790"; -+ compatible = "renesas,msiof-r8a7790", -+ "renesas,rcar-gen2-msiof"; - reg = <0 0xe6c90000 0 0x0064>; - interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>; -diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c -index d687f860a2da..84eefbc2b4f9 100644 ---- a/arch/arm/mach-at91/pm.c -+++ b/arch/arm/mach-at91/pm.c -@@ -332,7 +332,7 @@ static void at91sam9_sdram_standby(void) - at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); - } - --static const struct of_device_id const ramc_ids[] __initconst = { -+static const struct of_device_id ramc_ids[] __initconst = { - { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby }, - { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby }, - { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby }, -diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c -index cf3f8658f0e5..a55a7ecf146a 100644 ---- a/arch/arm/mach-bcm/bcm_kona_smc.c -+++ b/arch/arm/mach-bcm/bcm_kona_smc.c -@@ -33,7 +33,7 @@ struct bcm_kona_smc_data { - unsigned result; - }; - --static const struct of_device_id const bcm_kona_smc_ids[] __initconst = { -+static const struct of_device_id bcm_kona_smc_ids[] __initconst = { - {.compatible = "brcm,kona-smc"}, - {.compatible = "bcm,kona-smc"}, /* deprecated name */ - {}, -diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c -index 9b1dc223d8d3..e17a0e025f62 100644 ---- a/arch/arm/mach-cns3xxx/core.c -+++ b/arch/arm/mach-cns3xxx/core.c -@@ -346,7 +346,7 @@ static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = { - .power_off = csn3xxx_usb_power_off, - }; - --static const struct of_dev_auxdata const cns3xxx_auxdata[] __initconst = { -+static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = { - { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata }, - { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata }, - { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL }, -diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c -index 3fc2cbe52113..0ce4548ef7f0 100644 ---- a/arch/arm/mach-omap2/prm_common.c -+++ b/arch/arm/mach-omap2/prm_common.c -@@ -706,7 +706,7 @@ static struct omap_prcm_init_data scrm_data __initdata = { - }; - #endif - --static const struct of_device_id const omap_prcm_dt_match_table[] __initconst = { -+static const struct of_device_id omap_prcm_dt_match_table[] __initconst = { - #ifdef CONFIG_SOC_AM33XX - { .compatible = "ti,am3-prcm", .data = &am3_prm_data }, - #endif -diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c -index 2028167fff31..d76b1e5eb8ba 100644 ---- a/arch/arm/mach-omap2/vc.c -+++ b/arch/arm/mach-omap2/vc.c -@@ -559,7 +559,7 @@ struct i2c_init_data { - u8 hsscll_12; - }; - --static const struct i2c_init_data const omap4_i2c_timing_data[] __initconst = { -+static const struct i2c_init_data omap4_i2c_timing_data[] __initconst = { - { - .load = 50, - .loadbits = 0x3, -diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c -index 9ccffc1d0f28..aaaa6781b9fe 100644 ---- a/arch/arm/mach-spear/time.c -+++ b/arch/arm/mach-spear/time.c -@@ -204,7 +204,7 @@ static void __init spear_clockevent_init(int irq) - setup_irq(irq, &spear_timer_irq); - } - --static const struct of_device_id const timer_of_match[] __initconst = { -+static const struct of_device_id timer_of_match[] __initconst = { - { .compatible = "st,spear-timer", }, - { }, - }; -diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h -index ebb9efb02502..77edb22f855d 100644 ---- a/arch/mips/include/asm/irq.h -+++ b/arch/mips/include/asm/irq.h -@@ -18,9 +18,24 @@ - #include - - #define IRQ_STACK_SIZE THREAD_SIZE -+#define IRQ_STACK_START (IRQ_STACK_SIZE - sizeof(unsigned long)) - - extern void *irq_stack[NR_CPUS]; - -+/* -+ * The highest address on the IRQ stack contains a dummy frame put down in -+ * genex.S (handle_int & except_vec_vi_handler) which is structured as follows: -+ * -+ * top ------------ -+ * | task sp | <- irq_stack[cpu] + IRQ_STACK_START -+ * ------------ -+ * | | <- First frame of IRQ context -+ * ------------ -+ * -+ * task sp holds a copy of the task stack pointer where the struct pt_regs -+ * from exception entry can be found. -+ */ -+ - static inline bool on_irq_stack(int cpu, unsigned long sp) - { - unsigned long low = (unsigned long)irq_stack[cpu]; -diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c -index ec053ce7bb38..7ab8004c1659 100644 ---- a/arch/mips/kernel/asm-offsets.c -+++ b/arch/mips/kernel/asm-offsets.c -@@ -102,6 +102,7 @@ void output_thread_info_defines(void) - DEFINE(_THREAD_SIZE, THREAD_SIZE); - DEFINE(_THREAD_MASK, THREAD_MASK); - DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); -+ DEFINE(_IRQ_STACK_START, IRQ_STACK_START); - BLANK(); - } - -diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S -index 619e30e2c4f0..bb72f3ce7e29 100644 ---- a/arch/mips/kernel/genex.S -+++ b/arch/mips/kernel/genex.S -@@ -216,9 +216,11 @@ NESTED(handle_int, PT_SIZE, sp) - beq t0, t1, 2f - - /* Switch to IRQ stack */ -- li t1, _IRQ_STACK_SIZE -+ li t1, _IRQ_STACK_START - PTR_ADD sp, t0, t1 - -+ /* Save task's sp on IRQ stack so that unwinding can follow it */ -+ LONG_S s1, 0(sp) - 2: - jal plat_irq_dispatch - -@@ -326,9 +328,11 @@ NESTED(except_vec_vi_handler, 0, sp) - beq t0, t1, 2f - - /* Switch to IRQ stack */ -- li t1, _IRQ_STACK_SIZE -+ li t1, _IRQ_STACK_START - PTR_ADD sp, t0, t1 - -+ /* Save task's sp on IRQ stack so that unwinding can follow it */ -+ LONG_S s1, 0(sp) - 2: - jalr v0 - -diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c -index 8c26ecac930d..477ba026c3e5 100644 ---- a/arch/mips/kernel/process.c -+++ b/arch/mips/kernel/process.c -@@ -483,31 +483,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, - unsigned long pc, - unsigned long *ra) - { -+ unsigned long low, high, irq_stack_high; - struct mips_frame_info info; - unsigned long size, ofs; -+ struct pt_regs *regs; - int leaf; -- extern void ret_from_irq(void); -- extern void ret_from_exception(void); - - if (!stack_page) - return 0; - - /* -- * If we reached the bottom of interrupt context, -- * return saved pc in pt_regs. -+ * IRQ stacks start at IRQ_STACK_START -+ * task stacks at THREAD_SIZE - 32 - */ -- if (pc == (unsigned long)ret_from_irq || -- pc == (unsigned long)ret_from_exception) { -- struct pt_regs *regs; -- if (*sp >= stack_page && -- *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) { -- regs = (struct pt_regs *)*sp; -- pc = regs->cp0_epc; -- if (!user_mode(regs) && __kernel_text_address(pc)) { -- *sp = regs->regs[29]; -- *ra = regs->regs[31]; -- return pc; -- } -+ low = stack_page; -+ if (!preemptible() && on_irq_stack(raw_smp_processor_id(), *sp)) { -+ high = stack_page + IRQ_STACK_START; -+ irq_stack_high = high; -+ } else { -+ high = stack_page + THREAD_SIZE - 32; -+ irq_stack_high = 0; -+ } -+ -+ /* -+ * If we reached the top of the interrupt stack, start unwinding -+ * the interrupted task stack. -+ */ -+ if (unlikely(*sp == irq_stack_high)) { -+ unsigned long task_sp = *(unsigned long *)*sp; -+ -+ /* -+ * Check that the pointer saved in the IRQ stack head points to -+ * something within the stack of the current task -+ */ -+ if (!object_is_on_stack((void *)task_sp)) -+ return 0; -+ -+ /* -+ * Follow pointer to tasks kernel stack frame where interrupted -+ * state was saved. -+ */ -+ regs = (struct pt_regs *)task_sp; -+ pc = regs->cp0_epc; -+ if (!user_mode(regs) && __kernel_text_address(pc)) { -+ *sp = regs->regs[29]; -+ *ra = regs->regs[31]; -+ return pc; - } - return 0; - } -@@ -528,8 +549,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, - if (leaf < 0) - return 0; - -- if (*sp < stack_page || -- *sp + info.frame_size > stack_page + THREAD_SIZE - 32) -+ if (*sp < low || *sp + info.frame_size > high) - return 0; - - if (leaf) -diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S -index 0a93e83cd014..2026203c41e2 100644 ---- a/arch/mips/kernel/vmlinux.lds.S -+++ b/arch/mips/kernel/vmlinux.lds.S -@@ -159,7 +159,7 @@ SECTIONS - * Force .bss to 64K alignment so that .bss..swapper_pg_dir - * gets that alignment. .sbss should be empty, so there will be - * no holes after __init_end. */ -- BSS_SECTION(0, 0x10000, 0) -+ BSS_SECTION(0, 0x10000, 8) - - _end = . ; - -diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c -index daf580ce5ca2..2528181232fd 100644 ---- a/arch/mips/lantiq/xway/sysctrl.c -+++ b/arch/mips/lantiq/xway/sysctrl.c -@@ -469,8 +469,8 @@ void __init ltq_soc_init(void) - panic("Failed to load xbar nodes from devicetree"); - if (of_address_to_resource(np_xbar, 0, &res_xbar)) - panic("Failed to get xbar resources"); -- if (request_mem_region(res_xbar.start, resource_size(&res_xbar), -- res_xbar.name) < 0) -+ if (!request_mem_region(res_xbar.start, resource_size(&res_xbar), -+ res_xbar.name)) - panic("Failed to get xbar resources"); - - ltq_xbar_membase = ioremap_nocache(res_xbar.start, -diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c -index 3c575093f8f1..f2a6e1b8cce0 100644 ---- a/arch/mips/ralink/rt3883.c -+++ b/arch/mips/ralink/rt3883.c -@@ -144,5 +144,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) - - rt2880_pinmux_data = rt3883_pinmux_data; - -- ralink_soc == RT3883_SOC; -+ ralink_soc = RT3883_SOC; - } -diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c -index 518f4f5f1f43..d63d42533133 100644 ---- a/arch/parisc/kernel/perf.c -+++ b/arch/parisc/kernel/perf.c -@@ -39,7 +39,7 @@ - * the PDC INTRIGUE calls. This is done to eliminate bugs introduced - * in various PDC revisions. The code is much more maintainable - * and reliable this way vs having to debug on every version of PDC -- * on every box. -+ * on every box. - */ - - #include -@@ -195,8 +195,8 @@ static int perf_config(uint32_t *image_ptr); - static int perf_release(struct inode *inode, struct file *file); - static int perf_open(struct inode *inode, struct file *file); - static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos); --static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, -- loff_t *ppos); -+static ssize_t perf_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos); - static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg); - static void perf_start_counters(void); - static int perf_stop_counters(uint32_t *raddr); -@@ -222,7 +222,7 @@ extern void perf_intrigue_disable_perf_counters (void); - /* - * configure: - * -- * Configure the cpu with a given data image. First turn off the counters, -+ * Configure the cpu with a given data image. First turn off the counters, - * then download the image, then turn the counters back on. - */ - static int perf_config(uint32_t *image_ptr) -@@ -234,7 +234,7 @@ static int perf_config(uint32_t *image_ptr) - error = perf_stop_counters(raddr); - if (error != 0) { - printk("perf_config: perf_stop_counters = %ld\n", error); -- return -EINVAL; -+ return -EINVAL; - } - - printk("Preparing to write image\n"); -@@ -242,7 +242,7 @@ printk("Preparing to write image\n"); - error = perf_write_image((uint64_t *)image_ptr); - if (error != 0) { - printk("perf_config: DOWNLOAD = %ld\n", error); -- return -EINVAL; -+ return -EINVAL; - } - - printk("Preparing to start counters\n"); -@@ -254,7 +254,7 @@ printk("Preparing to start counters\n"); - } - - /* -- * Open the device and initialize all of its memory. The device is only -+ * Open the device and initialize all of its memory. The device is only - * opened once, but can be "queried" by multiple processes that know its - * file descriptor. - */ -@@ -298,8 +298,8 @@ static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t - * called on the processor that the download should happen - * on. - */ --static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, -- loff_t *ppos) -+static ssize_t perf_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) - { - int err; - size_t image_size; -@@ -307,11 +307,11 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun - uint32_t interface_type; - uint32_t test; - -- if (perf_processor_interface == ONYX_INTF) -+ if (perf_processor_interface == ONYX_INTF) - image_size = PCXU_IMAGE_SIZE; -- else if (perf_processor_interface == CUDA_INTF) -+ else if (perf_processor_interface == CUDA_INTF) - image_size = PCXW_IMAGE_SIZE; -- else -+ else - return -EFAULT; - - if (!capable(CAP_SYS_ADMIN)) -@@ -331,22 +331,22 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun - - /* First check the machine type is correct for - the requested image */ -- if (((perf_processor_interface == CUDA_INTF) && -- (interface_type != CUDA_INTF)) || -- ((perf_processor_interface == ONYX_INTF) && -- (interface_type != ONYX_INTF))) -+ if (((perf_processor_interface == CUDA_INTF) && -+ (interface_type != CUDA_INTF)) || -+ ((perf_processor_interface == ONYX_INTF) && -+ (interface_type != ONYX_INTF))) - return -EINVAL; - - /* Next check to make sure the requested image - is valid */ -- if (((interface_type == CUDA_INTF) && -+ if (((interface_type == CUDA_INTF) && - (test >= MAX_CUDA_IMAGES)) || -- ((interface_type == ONYX_INTF) && -- (test >= MAX_ONYX_IMAGES))) -+ ((interface_type == ONYX_INTF) && -+ (test >= MAX_ONYX_IMAGES))) - return -EINVAL; - - /* Copy the image into the processor */ -- if (interface_type == CUDA_INTF) -+ if (interface_type == CUDA_INTF) - return perf_config(cuda_images[test]); - else - return perf_config(onyx_images[test]); -@@ -360,7 +360,7 @@ static ssize_t perf_write(struct file *file, const char __user *buf, size_t coun - static void perf_patch_images(void) - { - #if 0 /* FIXME!! */ --/* -+/* - * NOTE: this routine is VERY specific to the current TLB image. - * If the image is changed, this routine might also need to be changed. - */ -@@ -368,9 +368,9 @@ static void perf_patch_images(void) - extern void $i_dtlb_miss_2_0(); - extern void PA2_0_iva(); - -- /* -+ /* - * We can only use the lower 32-bits, the upper 32-bits should be 0 -- * anyway given this is in the kernel -+ * anyway given this is in the kernel - */ - uint32_t itlb_addr = (uint32_t)&($i_itlb_miss_2_0); - uint32_t dtlb_addr = (uint32_t)&($i_dtlb_miss_2_0); -@@ -378,21 +378,21 @@ static void perf_patch_images(void) - - if (perf_processor_interface == ONYX_INTF) { - /* clear last 2 bytes */ -- onyx_images[TLBMISS][15] &= 0xffffff00; -+ onyx_images[TLBMISS][15] &= 0xffffff00; - /* set 2 bytes */ - onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); - onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00; - onyx_images[TLBMISS][17] = itlb_addr; - - /* clear last 2 bytes */ -- onyx_images[TLBHANDMISS][15] &= 0xffffff00; -+ onyx_images[TLBHANDMISS][15] &= 0xffffff00; - /* set 2 bytes */ - onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24)); - onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00; - onyx_images[TLBHANDMISS][17] = itlb_addr; - - /* clear last 2 bytes */ -- onyx_images[BIG_CPI][15] &= 0xffffff00; -+ onyx_images[BIG_CPI][15] &= 0xffffff00; - /* set 2 bytes */ - onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24)); - onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00; -@@ -405,24 +405,24 @@ static void perf_patch_images(void) - - } else if (perf_processor_interface == CUDA_INTF) { - /* Cuda interface */ -- cuda_images[TLBMISS][16] = -+ cuda_images[TLBMISS][16] = - (cuda_images[TLBMISS][16]&0xffff0000) | - ((dtlb_addr >> 8)&0x0000ffff); -- cuda_images[TLBMISS][17] = -+ cuda_images[TLBMISS][17] = - ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); - cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000; - -- cuda_images[TLBHANDMISS][16] = -+ cuda_images[TLBHANDMISS][16] = - (cuda_images[TLBHANDMISS][16]&0xffff0000) | - ((dtlb_addr >> 8)&0x0000ffff); -- cuda_images[TLBHANDMISS][17] = -+ cuda_images[TLBHANDMISS][17] = - ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); - cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000; - -- cuda_images[BIG_CPI][16] = -+ cuda_images[BIG_CPI][16] = - (cuda_images[BIG_CPI][16]&0xffff0000) | - ((dtlb_addr >> 8)&0x0000ffff); -- cuda_images[BIG_CPI][17] = -+ cuda_images[BIG_CPI][17] = - ((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff); - cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000; - } else { -@@ -434,7 +434,7 @@ static void perf_patch_images(void) - - /* - * ioctl routine -- * All routines effect the processor that they are executed on. Thus you -+ * All routines effect the processor that they are executed on. Thus you - * must be running on the processor that you wish to change. - */ - -@@ -460,7 +460,7 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - } - - /* copy out the Counters */ -- if (copy_to_user((void __user *)arg, raddr, -+ if (copy_to_user((void __user *)arg, raddr, - sizeof (raddr)) != 0) { - error = -EFAULT; - break; -@@ -488,7 +488,7 @@ static const struct file_operations perf_fops = { - .open = perf_open, - .release = perf_release - }; -- -+ - static struct miscdevice perf_dev = { - MISC_DYNAMIC_MINOR, - PA_PERF_DEV, -@@ -596,7 +596,7 @@ static int perf_stop_counters(uint32_t *raddr) - /* OR sticky2 (bit 1496) to counter2 bit 32 */ - tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000; - raddr[2] = (uint32_t)tmp64; -- -+ - /* Counter3 is bits 1497 to 1528 */ - tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff; - /* OR sticky3 (bit 1529) to counter3 bit 32 */ -@@ -618,7 +618,7 @@ static int perf_stop_counters(uint32_t *raddr) - userbuf[22] = 0; - userbuf[23] = 0; - -- /* -+ /* - * Write back the zeroed bytes + the image given - * the read was destructive. - */ -@@ -626,13 +626,13 @@ static int perf_stop_counters(uint32_t *raddr) - } else { - - /* -- * Read RDR-15 which contains the counters and sticky bits -+ * Read RDR-15 which contains the counters and sticky bits - */ - if (!perf_rdr_read_ubuf(15, userbuf)) { - return -13; - } - -- /* -+ /* - * Clear out the counters - */ - perf_rdr_clear(15); -@@ -645,7 +645,7 @@ static int perf_stop_counters(uint32_t *raddr) - raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL); - raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL); - } -- -+ - return 0; - } - -@@ -683,7 +683,7 @@ static int perf_rdr_read_ubuf(uint32_t rdr_num, uint64_t *buffer) - i = tentry->num_words; - while (i--) { - buffer[i] = 0; -- } -+ } - - /* Check for bits an even number of 64 */ - if ((xbits = width & 0x03f) != 0) { -@@ -809,18 +809,22 @@ static int perf_write_image(uint64_t *memaddr) - } - - runway = ioremap_nocache(cpu_device->hpa.start, 4096); -+ if (!runway) { -+ pr_err("perf_write_image: ioremap failed!\n"); -+ return -ENOMEM; -+ } - - /* Merge intrigue bits into Runway STATUS 0 */ - tmp64 = __raw_readq(runway + RUNWAY_STATUS) & 0xffecfffffffffffful; -- __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), -+ __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), - runway + RUNWAY_STATUS); -- -+ - /* Write RUNWAY DEBUG registers */ - for (i = 0; i < 8; i++) { - __raw_writeq(*memaddr++, runway + RUNWAY_DEBUG); - } - -- return 0; -+ return 0; - } - - /* -@@ -844,7 +848,7 @@ printk("perf_rdr_write\n"); - perf_rdr_shift_out_U(rdr_num, buffer[i]); - } else { - perf_rdr_shift_out_W(rdr_num, buffer[i]); -- } -+ } - } - printk("perf_rdr_write done\n"); - } -diff --git a/block/partitions/efi.c b/block/partitions/efi.c -index 26cb624ace05..d26d0d27f5fd 100644 ---- a/block/partitions/efi.c -+++ b/block/partitions/efi.c -@@ -293,7 +293,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, - if (!gpt) - return NULL; - -- count = le32_to_cpu(gpt->num_partition_entries) * -+ count = (size_t)le32_to_cpu(gpt->num_partition_entries) * - le32_to_cpu(gpt->sizeof_partition_entry); - if (!count) - return NULL; -@@ -352,7 +352,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, - gpt_header **gpt, gpt_entry **ptes) - { - u32 crc, origcrc; -- u64 lastlba; -+ u64 lastlba, pt_size; - - if (!ptes) - return 0; -@@ -434,13 +434,20 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, - goto fail; - } - -+ /* Sanity check partition table size */ -+ pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) * -+ le32_to_cpu((*gpt)->sizeof_partition_entry); -+ if (pt_size > KMALLOC_MAX_SIZE) { -+ pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n", -+ (unsigned long long)pt_size, KMALLOC_MAX_SIZE); -+ goto fail; -+ } -+ - if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) - goto fail; - - /* Check the GUID Partition Entry Array CRC */ -- crc = efi_crc32((const unsigned char *) (*ptes), -- le32_to_cpu((*gpt)->num_partition_entries) * -- le32_to_cpu((*gpt)->sizeof_partition_entry)); -+ crc = efi_crc32((const unsigned char *) (*ptes), pt_size); - - if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { - pr_debug("GUID Partitition Entry Array CRC check failed.\n"); -diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c -index e2d94972962d..7aa10c200ecb 100644 ---- a/drivers/ata/libata-transport.c -+++ b/drivers/ata/libata-transport.c -@@ -224,7 +224,6 @@ static DECLARE_TRANSPORT_CLASS(ata_port_class, - - static void ata_tport_release(struct device *dev) - { -- put_device(dev->parent); - } - - /** -@@ -284,7 +283,7 @@ int ata_tport_add(struct device *parent, - device_initialize(dev); - dev->type = &ata_port_type; - -- dev->parent = get_device(parent); -+ dev->parent = parent; - dev->release = ata_tport_release; - dev_set_name(dev, "ata%d", ap->print_id); - transport_setup_device(dev); -@@ -348,7 +347,6 @@ static DECLARE_TRANSPORT_CLASS(ata_link_class, - - static void ata_tlink_release(struct device *dev) - { -- put_device(dev->parent); - } - - /** -@@ -410,7 +408,7 @@ int ata_tlink_add(struct ata_link *link) - int error; - - device_initialize(dev); -- dev->parent = get_device(&ap->tdev); -+ dev->parent = &ap->tdev; - dev->release = ata_tlink_release; - if (ata_is_host_link(link)) - dev_set_name(dev, "link%d", ap->print_id); -@@ -588,7 +586,6 @@ static DECLARE_TRANSPORT_CLASS(ata_dev_class, - - static void ata_tdev_release(struct device *dev) - { -- put_device(dev->parent); - } - - /** -@@ -661,7 +658,7 @@ static int ata_tdev_add(struct ata_device *ata_dev) - int error; - - device_initialize(dev); -- dev->parent = get_device(&link->tdev); -+ dev->parent = &link->tdev; - dev->release = ata_tdev_release; - if (ata_is_host_link(link)) - dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno); -diff --git a/drivers/extcon/extcon-axp288.c b/drivers/extcon/extcon-axp288.c -index fd55c2f2080a..6c9d7ccebb8c 100644 ---- a/drivers/extcon/extcon-axp288.c -+++ b/drivers/extcon/extcon-axp288.c -@@ -168,7 +168,7 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) - return ret; - } - -- vbus_attach = (pwr_stat & PS_STAT_VBUS_PRESENT); -+ vbus_attach = (pwr_stat & PS_STAT_VBUS_VALID); - if (!vbus_attach) - goto notify_otg; - -diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c -index d24f35d74b27..ae70d2485ca1 100644 ---- a/drivers/firmware/psci.c -+++ b/drivers/firmware/psci.c -@@ -424,7 +424,7 @@ out_put_node: - return err; - } - --static const struct of_device_id const psci_of_match[] __initconst = { -+static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", .data = psci_0_1_init}, - { .compatible = "arm,psci-0.2", .data = psci_0_2_init}, - { .compatible = "arm,psci-1.0", .data = psci_0_2_init}, -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c -index b6e28dcaea1d..1fb1daa0b366 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c -@@ -739,8 +739,10 @@ int kfd_wait_on_events(struct kfd_process *p, - struct kfd_event_data event_data; - - if (copy_from_user(&event_data, &events[i], -- sizeof(struct kfd_event_data))) -+ sizeof(struct kfd_event_data))) { -+ ret = -EFAULT; - goto fail; -+ } - - ret = init_event_waiter(p, &event_waiters[i], - event_data.event_id, i); -diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c -index dee93ec87d02..84e0994aafdd 100644 ---- a/drivers/hwmon/gl520sm.c -+++ b/drivers/hwmon/gl520sm.c -@@ -208,11 +208,13 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, - } - static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); - --#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) --#define VDD_TO_REG(val) clamp_val((((val) * 4 + 47) / 95), 0, 255) -+#define VDD_FROM_REG(val) DIV_ROUND_CLOSEST((val) * 95, 4) -+#define VDD_CLAMP(val) clamp_val(val, 0, 255 * 95 / 4) -+#define VDD_TO_REG(val) DIV_ROUND_CLOSEST(VDD_CLAMP(val) * 4, 95) - --#define IN_FROM_REG(val) ((val) * 19) --#define IN_TO_REG(val) clamp_val((((val) + 9) / 19), 0, 255) -+#define IN_FROM_REG(val) ((val) * 19) -+#define IN_CLAMP(val) clamp_val(val, 0, 255 * 19) -+#define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19) - - static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, - char *buf) -@@ -349,8 +351,13 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, - - #define DIV_FROM_REG(val) (1 << (val)) - #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div)))) --#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \ -- clamp_val((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255)) -+ -+#define FAN_BASE(div) (480000 >> (div)) -+#define FAN_CLAMP(val, div) clamp_val(val, FAN_BASE(div) / 255, \ -+ FAN_BASE(div)) -+#define FAN_TO_REG(val, div) ((val) == 0 ? 0 : \ -+ DIV_ROUND_CLOSEST(480000, \ -+ FAN_CLAMP(val, div) << (div))) - - static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, - char *buf) -@@ -513,9 +520,9 @@ static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, - get_fan_off, set_fan_off); - --#define TEMP_FROM_REG(val) (((val) - 130) * 1000) --#define TEMP_TO_REG(val) clamp_val(((((val) < 0 ? \ -- (val) - 500 : (val) + 500) / 1000) + 130), 0, 255) -+#define TEMP_FROM_REG(val) (((val) - 130) * 1000) -+#define TEMP_CLAMP(val) clamp_val(val, -130000, 125000) -+#define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130) - - static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, - char *buf) -diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c -index 71d3929adf54..8d65f33af5da 100644 ---- a/drivers/i2c/busses/i2c-meson.c -+++ b/drivers/i2c/busses/i2c-meson.c -@@ -175,7 +175,7 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len) - wdata1 |= *buf++ << ((i - 4) * 8); - - writel(wdata0, i2c->regs + REG_TOK_WDATA0); -- writel(wdata0, i2c->regs + REG_TOK_WDATA1); -+ writel(wdata1, i2c->regs + REG_TOK_WDATA1); - - dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__, - wdata0, wdata1, len); -diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c -index 0c904edd6c00..f684fe31f832 100644 ---- a/drivers/iio/adc/axp288_adc.c -+++ b/drivers/iio/adc/axp288_adc.c -@@ -28,8 +28,6 @@ - #include - - #define AXP288_ADC_EN_MASK 0xF1 --#define AXP288_ADC_TS_PIN_GPADC 0xF2 --#define AXP288_ADC_TS_PIN_ON 0xF3 - - enum axp288_adc_id { - AXP288_ADC_TS, -@@ -123,16 +121,6 @@ static int axp288_adc_read_channel(int *val, unsigned long address, - return IIO_VAL_INT; - } - --static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, -- unsigned long address) --{ -- /* channels other than GPADC do not need to switch TS pin */ -- if (address != AXP288_GP_ADC_H) -- return 0; -- -- return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); --} -- - static int axp288_adc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -@@ -143,16 +131,7 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, - mutex_lock(&indio_dev->mlock); - switch (mask) { - case IIO_CHAN_INFO_RAW: -- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, -- chan->address)) { -- dev_err(&indio_dev->dev, "GPADC mode\n"); -- ret = -EINVAL; -- break; -- } - ret = axp288_adc_read_channel(val, chan->address, info->regmap); -- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, -- chan->address)) -- dev_err(&indio_dev->dev, "TS pin restore\n"); - break; - default: - ret = -EINVAL; -@@ -162,15 +141,6 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, - return ret; - } - --static int axp288_adc_set_state(struct regmap *regmap) --{ -- /* ADC should be always enabled for internal FG to function */ -- if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) -- return -EIO; -- -- return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); --} -- - static const struct iio_info axp288_adc_iio_info = { - .read_raw = &axp288_adc_read_raw, - .driver_module = THIS_MODULE, -@@ -199,7 +169,7 @@ static int axp288_adc_probe(struct platform_device *pdev) - * Set ADC to enabled state at all time, including system suspend. - * otherwise internal fuel gauge functionality may be affected. - */ -- ret = axp288_adc_set_state(axp20x->regmap); -+ ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); - if (ret) { - dev_err(&pdev->dev, "unable to enable ADC device\n"); - return ret; -diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c -index 6c8ff10101c0..77cc77ba998f 100644 ---- a/drivers/infiniband/hw/qib/qib_iba7322.c -+++ b/drivers/infiniband/hw/qib/qib_iba7322.c -@@ -7097,7 +7097,7 @@ static void qib_7322_txchk_change(struct qib_devdata *dd, u32 start, - unsigned long flags; - - while (wait) { -- unsigned long shadow; -+ unsigned long shadow = 0; - int cstart, previ = -1; - - /* -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c -index 6699ecd855f0..bad76eed06b3 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_main.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c -@@ -1239,7 +1239,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv) - rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); - /* remove from path/mc list */ -- list_del(&neigh->list); -+ list_del_init(&neigh->list); - call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - } else { - np = &neigh->hnext; -@@ -1406,7 +1406,7 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh) - rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); - /* remove from parent list */ -- list_del(&neigh->list); -+ list_del_init(&neigh->list); - call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - return; - } else { -@@ -1491,7 +1491,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid) - rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); - /* remove from parent list */ -- list_del(&neigh->list); -+ list_del_init(&neigh->list); - call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - } else { - np = &neigh->hnext; -@@ -1533,7 +1533,7 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv) - rcu_dereference_protected(neigh->hnext, - lockdep_is_held(&priv->lock))); - /* remove from path/mc list */ -- list_del(&neigh->list); -+ list_del_init(&neigh->list); - call_rcu(&neigh->rcu, ipoib_neigh_reclaim); - } - } -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c -index 57a34f87dedf..9b47a437d6c9 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c -@@ -160,11 +160,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) - out: - up_write(&ppriv->vlan_rwsem); - -+ rtnl_unlock(); -+ - if (result) - free_netdev(priv->dev); - -- rtnl_unlock(); -- - return result; - } - -@@ -185,7 +185,6 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) - list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { - if (priv->pkey == pkey && - priv->child_type == IPOIB_LEGACY_CHILD) { -- unregister_netdevice(priv->dev); - list_del(&priv->list); - dev = priv->dev; - break; -@@ -193,6 +192,11 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) - } - up_write(&ppriv->vlan_rwsem); - -+ if (dev) { -+ ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name); -+ unregister_netdevice(dev); -+ } -+ - rtnl_unlock(); - - if (dev) { -diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c -index dad768caa9c5..18751b1dfd3d 100644 ---- a/drivers/iommu/io-pgtable-arm.c -+++ b/drivers/iommu/io-pgtable-arm.c -@@ -335,8 +335,12 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova, - if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS) - pte |= ARM_LPAE_PTE_NSTABLE; - __arm_lpae_set_pte(ptep, pte, cfg); -- } else { -+ } else if (!iopte_leaf(pte, lvl)) { - cptep = iopte_deref(pte, data); -+ } else { -+ /* We require an unmap first */ -+ WARN_ON(!selftest_running); -+ return -EEXIST; - } - - /* Rinse, repeat */ -diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c -index e5ee4e9e0ea5..a8a86d450d76 100644 ---- a/drivers/md/raid10.c -+++ b/drivers/md/raid10.c -@@ -1414,11 +1414,24 @@ retry_write: - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); -+ -+ cb = blk_check_plugged(raid10_unplug, mddev, -+ sizeof(*plug)); -+ if (cb) -+ plug = container_of(cb, struct raid10_plug_cb, -+ cb); -+ else -+ plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); -- bio_list_add(&conf->pending_bio_list, mbio); -- conf->pending_count++; -+ if (plug) { -+ bio_list_add(&plug->pending, mbio); -+ plug->pending_cnt++; -+ } else { -+ bio_list_add(&conf->pending_bio_list, mbio); -+ conf->pending_count++; -+ } - spin_unlock_irqrestore(&conf->device_lock, flags); -- if (!mddev_check_plugged(mddev)) -+ if (!plug) - md_wakeup_thread(mddev->thread); - } - } -diff --git a/drivers/media/pci/ttpci/av7110_hw.c b/drivers/media/pci/ttpci/av7110_hw.c -index 300bd3c94738..0992bb0e207e 100644 ---- a/drivers/media/pci/ttpci/av7110_hw.c -+++ b/drivers/media/pci/ttpci/av7110_hw.c -@@ -56,11 +56,11 @@ - by Nathan Laredo */ - - int av7110_debiwrite(struct av7110 *av7110, u32 config, -- int addr, u32 val, int count) -+ int addr, u32 val, unsigned int count) - { - struct saa7146_dev *dev = av7110->dev; - -- if (count <= 0 || count > 32764) { -+ if (count > 32764) { - printk("%s: invalid count %d\n", __func__, count); - return -1; - } -@@ -78,12 +78,12 @@ int av7110_debiwrite(struct av7110 *av7110, u32 config, - return 0; - } - --u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count) -+u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, unsigned int count) - { - struct saa7146_dev *dev = av7110->dev; - u32 result = 0; - -- if (count > 32764 || count <= 0) { -+ if (count > 32764) { - printk("%s: invalid count %d\n", __func__, count); - return 0; - } -diff --git a/drivers/media/pci/ttpci/av7110_hw.h b/drivers/media/pci/ttpci/av7110_hw.h -index 1634aba5cb84..ccb148059406 100644 ---- a/drivers/media/pci/ttpci/av7110_hw.h -+++ b/drivers/media/pci/ttpci/av7110_hw.h -@@ -377,14 +377,14 @@ extern int av7110_fw_request(struct av7110 *av7110, u16 *request_buf, - - /* DEBI (saa7146 data extension bus interface) access */ - extern int av7110_debiwrite(struct av7110 *av7110, u32 config, -- int addr, u32 val, int count); -+ int addr, u32 val, unsigned int count); - extern u32 av7110_debiread(struct av7110 *av7110, u32 config, -- int addr, int count); -+ int addr, unsigned int count); - - - /* DEBI during interrupt */ - /* single word writes */ --static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) -+static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count) - { - av7110_debiwrite(av7110, config, addr, val, count); - } -@@ -397,7 +397,7 @@ static inline void mwdebi(struct av7110 *av7110, u32 config, int addr, - av7110_debiwrite(av7110, config, addr, 0, count); - } - --static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) -+static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count) - { - u32 res; - -@@ -408,7 +408,7 @@ static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, i - } - - /* DEBI outside interrupts, only for count <= 4! */ --static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) -+static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count) - { - unsigned long flags; - -@@ -417,7 +417,7 @@ static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, i - spin_unlock_irqrestore(&av7110->debilock, flags); - } - --static inline u32 rdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) -+static inline u32 rdebi(struct av7110 *av7110, u32 config, int addr, u32 val, unsigned int count) - { - unsigned long flags; - u32 res; -diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c -index 9b9e423e4fc4..15c543d4b366 100644 ---- a/drivers/media/platform/exynos-gsc/gsc-core.c -+++ b/drivers/media/platform/exynos-gsc/gsc-core.c -@@ -849,9 +849,7 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, - - if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) || - (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) || -- (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) || - (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) || -- (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) || - (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M)) - swap(addr->cb, addr->cr); - -diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c -index 7e327a6dd53d..c23bc4f331bd 100644 ---- a/drivers/mmc/core/sdio_bus.c -+++ b/drivers/mmc/core/sdio_bus.c -@@ -266,7 +266,7 @@ static void sdio_release_func(struct device *dev) - sdio_free_func_cis(func); - - kfree(func->info); -- -+ kfree(func->tmpbuf); - kfree(func); - } - -@@ -281,6 +281,16 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) - if (!func) - return ERR_PTR(-ENOMEM); - -+ /* -+ * allocate buffer separately to make sure it's properly aligned for -+ * DMA usage (incl. 64 bit DMA) -+ */ -+ func->tmpbuf = kmalloc(4, GFP_KERNEL); -+ if (!func->tmpbuf) { -+ kfree(func); -+ return ERR_PTR(-ENOMEM); -+ } -+ - func->card = card; - - device_initialize(&func->dev); -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index fa3b4cbea23b..a481ea64e287 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -7658,6 +7658,11 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - -+ /* In case of PCI error, adapter lose its HW address -+ * so we should re-assign it here. -+ */ -+ hw->hw_addr = adapter->io_addr; -+ - igb_reset(adapter); - wr32(E1000_WUS, ~0); - result = PCI_ERS_RESULT_RECOVERED; -diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h -index 72fcfc924589..0d18be0fed8e 100644 ---- a/drivers/net/ethernet/renesas/sh_eth.h -+++ b/drivers/net/ethernet/renesas/sh_eth.h -@@ -339,7 +339,7 @@ enum FELIC_MODE_BIT { - ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000, - ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, - ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, -- ECMR_PMDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, -+ ECMR_MPDE = 0x00000200, ECMR_RE = 0x00000040, ECMR_TE = 0x00000020, - ECMR_RTM = 0x00000010, ECMR_ILB = 0x00000008, ECMR_ELB = 0x00000004, - ECMR_DM = 0x00000002, ECMR_PRM = 0x00000001, - }; -diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c -index a5f392ae30d5..61cd53838360 100644 ---- a/drivers/net/team/team.c -+++ b/drivers/net/team/team.c -@@ -2343,8 +2343,10 @@ start_again: - - hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, - TEAM_CMD_OPTIONS_GET); -- if (!hdr) -+ if (!hdr) { -+ nlmsg_free(skb); - return -EMSGSIZE; -+ } - - if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) - goto nla_put_failure; -@@ -2611,8 +2613,10 @@ start_again: - - hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI, - TEAM_CMD_PORT_LIST_GET); -- if (!hdr) -+ if (!hdr) { -+ nlmsg_free(skb); - return -EMSGSIZE; -+ } - - if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) - goto nla_put_failure; -diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig -index 7f83504dfa69..1f6893ebce16 100644 ---- a/drivers/net/usb/Kconfig -+++ b/drivers/net/usb/Kconfig -@@ -364,7 +364,7 @@ config USB_NET_NET1080 - optionally with LEDs that indicate traffic - - config USB_NET_PLUSB -- tristate "Prolific PL-2301/2302/25A1 based cables" -+ tristate "Prolific PL-2301/2302/25A1/27A1 based cables" - # if the handshake/init/reset problems, from original 'plusb', - # are ever resolved ... then remove "experimental" - depends on USB_USBNET -diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c -index 1bfe0fcaccf5..7c02231c1a1b 100644 ---- a/drivers/net/usb/plusb.c -+++ b/drivers/net/usb/plusb.c -@@ -102,7 +102,7 @@ static int pl_reset(struct usbnet *dev) - } - - static const struct driver_info prolific_info = { -- .description = "Prolific PL-2301/PL-2302/PL-25A1", -+ .description = "Prolific PL-2301/PL-2302/PL-25A1/PL-27A1", - .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, - /* some PL-2302 versions seem to fail usb_set_interface() */ - .reset = pl_reset, -@@ -139,6 +139,17 @@ static const struct usb_device_id products [] = { - * Host-to-Host Cable - */ - .driver_info = (unsigned long) &prolific_info, -+ -+}, -+ -+/* super speed cables */ -+{ -+ USB_DEVICE(0x067b, 0x27a1), /* PL-27A1, no eeprom -+ * also: goobay Active USB 3.0 -+ * Data Link, -+ * Unitek Y-3501 -+ */ -+ .driver_info = (unsigned long) &prolific_info, - }, - - { }, // END -@@ -158,5 +169,5 @@ static struct usb_driver plusb_driver = { - module_usb_driver(plusb_driver); - - MODULE_AUTHOR("David Brownell"); --MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"); -+MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1/27A1 USB Host to Host Link Driver"); - MODULE_LICENSE("GPL"); -diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c -index 0f82c0b146f6..e04b57f79df8 100644 ---- a/drivers/tty/goldfish.c -+++ b/drivers/tty/goldfish.c -@@ -293,7 +293,7 @@ static int goldfish_tty_probe(struct platform_device *pdev) - return 0; - - err_tty_register_device_failed: -- free_irq(irq, pdev); -+ free_irq(irq, qtty); - err_request_irq_failed: - goldfish_tty_current_line_count--; - if (goldfish_tty_current_line_count == 0) -diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c -index 0cf149edddd8..f36a1ac3bfbd 100644 ---- a/drivers/usb/chipidea/otg.c -+++ b/drivers/usb/chipidea/otg.c -@@ -134,9 +134,9 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) - if (!ci->is_otg) - return; - -- if (hw_read_otgsc(ci, OTGSC_BSV)) -+ if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) - usb_gadget_vbus_connect(&ci->gadget); -- else -+ else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active) - usb_gadget_vbus_disconnect(&ci->gadget); - } - -@@ -175,14 +175,21 @@ static void ci_handle_id_switch(struct ci_hdrc *ci) - - ci_role_stop(ci); - -- if (role == CI_ROLE_GADGET) -+ if (role == CI_ROLE_GADGET && -+ IS_ERR(ci->platdata->vbus_extcon.edev)) - /* -- * wait vbus lower than OTGSC_BSV before connecting -- * to host -+ * Wait vbus lower than OTGSC_BSV before connecting -+ * to host. If connecting status is from an external -+ * connector instead of register, we don't need to -+ * care vbus on the board, since it will not affect -+ * external connector status. - */ - hw_wait_vbus_lower_bsv(ci); - - ci_role_start(ci, role); -+ /* vbus change may have already occurred */ -+ if (role == CI_ROLE_GADGET) -+ ci_handle_vbus_change(ci); - } - } - /** -diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c -index e56cdb436de3..4581fa1dec98 100644 ---- a/drivers/usb/serial/mos7720.c -+++ b/drivers/usb/serial/mos7720.c -@@ -234,11 +234,16 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, - - status = usb_control_msg(usbdev, pipe, request, requesttype, value, - index, buf, 1, MOS_WDR_TIMEOUT); -- if (status == 1) -+ if (status == 1) { - *data = *buf; -- else if (status < 0) -+ } else { - dev_err(&usbdev->dev, - "mos7720: usb_control_msg() failed: %d\n", status); -+ if (status >= 0) -+ status = -EIO; -+ *data = 0; -+ } -+ - kfree(buf); - - return status; -diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c -index d17685cc00c9..ed883a7ad533 100644 ---- a/drivers/usb/serial/mos7840.c -+++ b/drivers/usb/serial/mos7840.c -@@ -285,9 +285,15 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH, - MOS_WDR_TIMEOUT); -+ if (ret < VENDOR_READ_LENGTH) { -+ if (ret >= 0) -+ ret = -EIO; -+ goto out; -+ } -+ - *val = buf[0]; - dev_dbg(&port->dev, "%s offset is %x, return val %x\n", __func__, reg, *val); -- -+out: - kfree(buf); - return ret; - } -@@ -353,8 +359,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, - MOS_WDR_TIMEOUT); -+ if (ret < VENDOR_READ_LENGTH) { -+ if (ret >= 0) -+ ret = -EIO; -+ goto out; -+ } - *val = buf[0]; -- -+out: - kfree(buf); - return ret; - } -@@ -1490,10 +1501,10 @@ static int mos7840_tiocmget(struct tty_struct *tty) - return -ENODEV; - - status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); -- if (status != 1) -+ if (status < 0) - return -EIO; - status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); -- if (status != 1) -+ if (status < 0) - return -EIO; - result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) - | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) -diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c -index ff36f5475d7e..09a0cf5f3dd8 100644 ---- a/fs/gfs2/glock.c -+++ b/fs/gfs2/glock.c -@@ -1798,16 +1798,18 @@ void gfs2_glock_exit(void) - - static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi) - { -- do { -- gi->gl = rhashtable_walk_next(&gi->hti); -+ while ((gi->gl = rhashtable_walk_next(&gi->hti))) { - if (IS_ERR(gi->gl)) { - if (PTR_ERR(gi->gl) == -EAGAIN) - continue; - gi->gl = NULL; -+ return; - } -- /* Skip entries for other sb and dead entries */ -- } while ((gi->gl) && ((gi->sdp != gi->gl->gl_name.ln_sbd) || -- __lockref_is_dead(&gi->gl->gl_lockref))); -+ /* Skip entries for other sb and dead entries */ -+ if (gi->sdp == gi->gl->gl_name.ln_sbd && -+ !__lockref_is_dead(&gi->gl->gl_lockref)) -+ return; -+ } - } - - static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) -diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c -index 686ba6fb20dd..8067364c602f 100644 ---- a/fs/xfs/kmem.c -+++ b/fs/xfs/kmem.c -@@ -24,24 +24,6 @@ - #include "kmem.h" - #include "xfs_message.h" - --/* -- * Greedy allocation. May fail and may return vmalloced memory. -- */ --void * --kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) --{ -- void *ptr; -- size_t kmsize = maxsize; -- -- while (!(ptr = vzalloc(kmsize))) { -- if ((kmsize >>= 1) <= minsize) -- kmsize = minsize; -- } -- if (ptr) -- *size = kmsize; -- return ptr; --} -- - void * - kmem_alloc(size_t size, xfs_km_flags_t flags) - { -diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h -index cc6b768fc068..ae45f77ce33b 100644 ---- a/fs/xfs/kmem.h -+++ b/fs/xfs/kmem.h -@@ -69,8 +69,6 @@ static inline void kmem_free(const void *ptr) - } - - --extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); -- - static inline void * - kmem_zalloc(size_t size, xfs_km_flags_t flags) - { -diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c -index 930ebd86beba..99a4891c00ab 100644 ---- a/fs/xfs/xfs_itable.c -+++ b/fs/xfs/xfs_itable.c -@@ -351,7 +351,6 @@ xfs_bulkstat( - xfs_agino_t agino; /* inode # in allocation group */ - xfs_agnumber_t agno; /* allocation group number */ - xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ -- size_t irbsize; /* size of irec buffer in bytes */ - xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ - int nirbuf; /* size of irbuf */ - int ubcount; /* size of user's buffer */ -@@ -378,11 +377,10 @@ xfs_bulkstat( - *ubcountp = 0; - *done = 0; - -- irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4); -+ irbuf = kmem_zalloc_large(PAGE_SIZE * 4, KM_SLEEP); - if (!irbuf) - return -ENOMEM; -- -- nirbuf = irbsize / sizeof(*irbuf); -+ nirbuf = (PAGE_SIZE * 4) / sizeof(*irbuf); - - /* - * Loop over the allocation groups, starting from the last -diff --git a/include/linux/audit.h b/include/linux/audit.h -index 20eba1eb0a3c..faac391badac 100644 ---- a/include/linux/audit.h -+++ b/include/linux/audit.h -@@ -281,6 +281,20 @@ static inline int audit_socketcall(int nargs, unsigned long *args) - return __audit_socketcall(nargs, args); - return 0; - } -+ -+static inline int audit_socketcall_compat(int nargs, u32 *args) -+{ -+ unsigned long a[AUDITSC_ARGS]; -+ int i; -+ -+ if (audit_dummy_context()) -+ return 0; -+ -+ for (i = 0; i < nargs; i++) -+ a[i] = (unsigned long)args[i]; -+ return __audit_socketcall(nargs, a); -+} -+ - static inline int audit_sockaddr(int len, void *addr) - { - if (unlikely(!audit_dummy_context())) -@@ -407,6 +421,12 @@ static inline int audit_socketcall(int nargs, unsigned long *args) - { - return 0; - } -+ -+static inline int audit_socketcall_compat(int nargs, u32 *args) -+{ -+ return 0; -+} -+ - static inline void audit_fd_pair(int fd1, int fd2) - { } - static inline int audit_sockaddr(int len, void *addr) -diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h -index aab032a6ae61..97ca105347a6 100644 ---- a/include/linux/mmc/sdio_func.h -+++ b/include/linux/mmc/sdio_func.h -@@ -53,7 +53,7 @@ struct sdio_func { - unsigned int state; /* function state */ - #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ - -- u8 tmpbuf[4]; /* DMA:able scratch buffer */ -+ u8 *tmpbuf; /* DMA:able scratch buffer */ - - unsigned num_info; /* number of info strings */ - const char **info; /* info strings */ -diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h -index 0b69a7753558..f28f79966e9e 100644 ---- a/include/uapi/drm/drm_fourcc.h -+++ b/include/uapi/drm/drm_fourcc.h -@@ -150,6 +150,7 @@ - - /* Vendor Ids: */ - #define DRM_FORMAT_MOD_NONE 0 -+#define DRM_FORMAT_MOD_VENDOR_NONE 0 - #define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 - #define DRM_FORMAT_MOD_VENDOR_AMD 0x02 - #define DRM_FORMAT_MOD_VENDOR_NV 0x03 -diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c -index ff8bb41d713f..a1f697ec4fc2 100644 ---- a/net/bridge/br_netlink.c -+++ b/net/bridge/br_netlink.c -@@ -1073,11 +1073,14 @@ static int br_dev_newlink(struct net *src_net, struct net_device *dev, - spin_unlock_bh(&br->lock); - } - -- err = br_changelink(dev, tb, data); -+ err = register_netdevice(dev); - if (err) - return err; - -- return register_netdevice(dev); -+ err = br_changelink(dev, tb, data); -+ if (err) -+ unregister_netdevice(dev); -+ return err; - } - - static size_t br_get_size(const struct net_device *brdev) -diff --git a/net/compat.c b/net/compat.c -index 5cfd26a0006f..0ccf3ecf6bbb 100644 ---- a/net/compat.c -+++ b/net/compat.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -767,14 +768,24 @@ COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, - - COMPAT_SYSCALL_DEFINE2(socketcall, int, call, u32 __user *, args) - { -- int ret; -- u32 a[6]; -+ u32 a[AUDITSC_ARGS]; -+ unsigned int len; - u32 a0, a1; -+ int ret; - - if (call < SYS_SOCKET || call > SYS_SENDMMSG) - return -EINVAL; -- if (copy_from_user(a, args, nas[call])) -+ len = nas[call]; -+ if (len > sizeof(a)) -+ return -EINVAL; -+ -+ if (copy_from_user(a, args, len)) - return -EFAULT; -+ -+ ret = audit_socketcall_compat(len / sizeof(a[0]), a); -+ if (ret) -+ return ret; -+ - a0 = a[0]; - a1 = a[1]; - -diff --git a/net/core/dev.c b/net/core/dev.c -index 24d243084aab..dac52fa60f25 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -2338,6 +2338,9 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason) - { - unsigned long flags; - -+ if (unlikely(!skb)) -+ return; -+ - if (likely(atomic_read(&skb->users) == 1)) { - smp_rmb(); - atomic_set(&skb->users, 0); -diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c -index ddb894ac1458..2689c9c4f1a0 100644 ---- a/net/ipv4/netfilter/nf_nat_snmp_basic.c -+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c -@@ -1304,6 +1304,7 @@ static int __init nf_nat_snmp_basic_init(void) - static void __exit nf_nat_snmp_basic_fini(void) - { - RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); -+ synchronize_rcu(); - nf_conntrack_helper_unregister(&snmp_trap_helper); - } - -diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c -index 4e78c57b818f..f3b92ce463b0 100644 ---- a/net/netfilter/nf_conntrack_ecache.c -+++ b/net/netfilter/nf_conntrack_ecache.c -@@ -200,6 +200,7 @@ void nf_conntrack_unregister_notifier(struct net *net, - BUG_ON(notify != new); - RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); - mutex_unlock(&nf_ct_ecache_mutex); -+ /* synchronize_rcu() is called from ctnetlink_exit. */ - } - EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); - -@@ -236,6 +237,7 @@ void nf_ct_expect_unregister_notifier(struct net *net, - BUG_ON(notify != new); - RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); - mutex_unlock(&nf_ct_ecache_mutex); -+ /* synchronize_rcu() is called from ctnetlink_exit. */ - } - EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); - -diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c -index e565b2becb14..660939df7c94 100644 ---- a/net/netfilter/nf_conntrack_netlink.c -+++ b/net/netfilter/nf_conntrack_netlink.c -@@ -3415,6 +3415,7 @@ static void __exit ctnetlink_exit(void) - #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT - RCU_INIT_POINTER(nfnl_ct_hook, NULL); - #endif -+ synchronize_rcu(); - } - - module_init(ctnetlink_init); -diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c -index 06a9f45771ab..44516c90118a 100644 ---- a/net/netfilter/nf_nat_core.c -+++ b/net/netfilter/nf_nat_core.c -@@ -892,6 +892,8 @@ static void __exit nf_nat_cleanup(void) - #ifdef CONFIG_XFRM - RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); - #endif -+ synchronize_rcu(); -+ - for (i = 0; i < NFPROTO_NUMPROTO; i++) - kfree(nf_nat_l4protos[i]); - synchronize_net(); -diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c -index 54330fb5efaf..6d10002d23f8 100644 ---- a/net/netfilter/nfnetlink_cthelper.c -+++ b/net/netfilter/nfnetlink_cthelper.c -@@ -161,6 +161,7 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, - int i, ret; - struct nf_conntrack_expect_policy *expect_policy; - struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; -+ unsigned int class_max; - - ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, - nfnl_cthelper_expect_policy_set); -@@ -170,19 +171,18 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, - if (!tb[NFCTH_POLICY_SET_NUM]) - return -EINVAL; - -- helper->expect_class_max = -- ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); -- -- if (helper->expect_class_max != 0 && -- helper->expect_class_max > NF_CT_MAX_EXPECT_CLASSES) -+ class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); -+ if (class_max == 0) -+ return -EINVAL; -+ if (class_max > NF_CT_MAX_EXPECT_CLASSES) - return -EOVERFLOW; - - expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) * -- helper->expect_class_max, GFP_KERNEL); -+ class_max, GFP_KERNEL); - if (expect_policy == NULL) - return -ENOMEM; - -- for (i=0; iexpect_class_max; i++) { -+ for (i = 0; i < class_max; i++) { - if (!tb[NFCTH_POLICY_SET+i]) - goto err; - -@@ -191,6 +191,8 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, - if (ret < 0) - goto err; - } -+ -+ helper->expect_class_max = class_max - 1; - helper->expect_policy = expect_policy; - return 0; - err: -@@ -377,10 +379,10 @@ nfnl_cthelper_dump_policy(struct sk_buff *skb, - goto nla_put_failure; - - if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM, -- htonl(helper->expect_class_max))) -+ htonl(helper->expect_class_max + 1))) - goto nla_put_failure; - -- for (i=0; iexpect_class_max; i++) { -+ for (i = 0; i < helper->expect_class_max + 1; i++) { - nest_parms2 = nla_nest_start(skb, - (NFCTH_POLICY_SET+i) | NLA_F_NESTED); - if (nest_parms2 == NULL) -diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c -index c7a2d0e1c462..ed9153bd7e73 100644 ---- a/net/netfilter/nfnetlink_cttimeout.c -+++ b/net/netfilter/nfnetlink_cttimeout.c -@@ -611,8 +611,8 @@ static void __exit cttimeout_exit(void) - #ifdef CONFIG_NF_CONNTRACK_TIMEOUT - RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); - RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); -+ synchronize_rcu(); - #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ -- rcu_barrier(); - } - - module_init(cttimeout_init); -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 148ec130d99d..b70055fc30cb 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -3802,6 +3802,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, - case PACKET_HDRLEN: - if (len > sizeof(int)) - len = sizeof(int); -+ if (len < sizeof(int)) -+ return -EINVAL; - if (copy_from_user(&val, optval, len)) - return -EFAULT; - switch (val) { -diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c -index da5a7fb98c77..a6f5b3d21571 100644 ---- a/net/rds/ib_cm.c -+++ b/net/rds/ib_cm.c -@@ -381,7 +381,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - ret = PTR_ERR(ic->i_send_cq); - ic->i_send_cq = NULL; - rdsdebug("ib_create_cq send failed: %d\n", ret); -- goto out; -+ goto rds_ibdev_out; - } - - cq_attr.cqe = ic->i_recv_ring.w_nr; -@@ -392,19 +392,19 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - ret = PTR_ERR(ic->i_recv_cq); - ic->i_recv_cq = NULL; - rdsdebug("ib_create_cq recv failed: %d\n", ret); -- goto out; -+ goto send_cq_out; - } - - ret = ib_req_notify_cq(ic->i_send_cq, IB_CQ_NEXT_COMP); - if (ret) { - rdsdebug("ib_req_notify_cq send failed: %d\n", ret); -- goto out; -+ goto recv_cq_out; - } - - ret = ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); - if (ret) { - rdsdebug("ib_req_notify_cq recv failed: %d\n", ret); -- goto out; -+ goto recv_cq_out; - } - - /* XXX negotiate max send/recv with remote? */ -@@ -428,7 +428,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - ret = rdma_create_qp(ic->i_cm_id, ic->i_pd, &attr); - if (ret) { - rdsdebug("rdma_create_qp failed: %d\n", ret); -- goto out; -+ goto recv_cq_out; - } - - ic->i_send_hdrs = ib_dma_alloc_coherent(dev, -@@ -438,7 +438,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - if (!ic->i_send_hdrs) { - ret = -ENOMEM; - rdsdebug("ib_dma_alloc_coherent send failed\n"); -- goto out; -+ goto qp_out; - } - - ic->i_recv_hdrs = ib_dma_alloc_coherent(dev, -@@ -448,7 +448,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - if (!ic->i_recv_hdrs) { - ret = -ENOMEM; - rdsdebug("ib_dma_alloc_coherent recv failed\n"); -- goto out; -+ goto send_hdrs_dma_out; - } - - ic->i_ack = ib_dma_alloc_coherent(dev, sizeof(struct rds_header), -@@ -456,7 +456,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - if (!ic->i_ack) { - ret = -ENOMEM; - rdsdebug("ib_dma_alloc_coherent ack failed\n"); -- goto out; -+ goto recv_hdrs_dma_out; - } - - ic->i_sends = vzalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work), -@@ -464,7 +464,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - if (!ic->i_sends) { - ret = -ENOMEM; - rdsdebug("send allocation failed\n"); -- goto out; -+ goto ack_dma_out; - } - - ic->i_recvs = vzalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work), -@@ -472,7 +472,7 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - if (!ic->i_recvs) { - ret = -ENOMEM; - rdsdebug("recv allocation failed\n"); -- goto out; -+ goto sends_out; - } - - rds_ib_recv_init_ack(ic); -@@ -480,8 +480,33 @@ static int rds_ib_setup_qp(struct rds_connection *conn) - rdsdebug("conn %p pd %p cq %p %p\n", conn, ic->i_pd, - ic->i_send_cq, ic->i_recv_cq); - --out: -+ return ret; -+ -+sends_out: -+ vfree(ic->i_sends); -+ack_dma_out: -+ ib_dma_free_coherent(dev, sizeof(struct rds_header), -+ ic->i_ack, ic->i_ack_dma); -+recv_hdrs_dma_out: -+ ib_dma_free_coherent(dev, ic->i_recv_ring.w_nr * -+ sizeof(struct rds_header), -+ ic->i_recv_hdrs, ic->i_recv_hdrs_dma); -+send_hdrs_dma_out: -+ ib_dma_free_coherent(dev, ic->i_send_ring.w_nr * -+ sizeof(struct rds_header), -+ ic->i_send_hdrs, ic->i_send_hdrs_dma); -+qp_out: -+ rdma_destroy_qp(ic->i_cm_id); -+recv_cq_out: -+ if (!ib_destroy_cq(ic->i_recv_cq)) -+ ic->i_recv_cq = NULL; -+send_cq_out: -+ if (!ib_destroy_cq(ic->i_send_cq)) -+ ic->i_send_cq = NULL; -+rds_ibdev_out: -+ rds_ib_remove_conn(rds_ibdev, conn); - rds_ib_dev_put(rds_ibdev); -+ - return ret; - } - -diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c -index eac30bf486d7..094e2a12860a 100644 ---- a/net/rds/ib_send.c -+++ b/net/rds/ib_send.c -@@ -68,16 +68,6 @@ static void rds_ib_send_complete(struct rds_message *rm, - complete(rm, notify_status); - } - --static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, -- struct rm_data_op *op, -- int wc_status) --{ -- if (op->op_nents) -- ib_dma_unmap_sg(ic->i_cm_id->device, -- op->op_sg, op->op_nents, -- DMA_TO_DEVICE); --} -- - static void rds_ib_send_unmap_rdma(struct rds_ib_connection *ic, - struct rm_rdma_op *op, - int wc_status) -@@ -138,6 +128,21 @@ static void rds_ib_send_unmap_atomic(struct rds_ib_connection *ic, - rds_ib_stats_inc(s_ib_atomic_fadd); - } - -+static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, -+ struct rm_data_op *op, -+ int wc_status) -+{ -+ struct rds_message *rm = container_of(op, struct rds_message, data); -+ -+ if (op->op_nents) -+ ib_dma_unmap_sg(ic->i_cm_id->device, -+ op->op_sg, op->op_nents, -+ DMA_TO_DEVICE); -+ -+ if (rm->rdma.op_active && rm->data.op_notify) -+ rds_ib_send_unmap_rdma(ic, &rm->rdma, wc_status); -+} -+ - /* - * Unmap the resources associated with a struct send_work. - * -diff --git a/net/rds/rdma.c b/net/rds/rdma.c -index 4c93badeabf2..8d3a851a3476 100644 ---- a/net/rds/rdma.c -+++ b/net/rds/rdma.c -@@ -626,6 +626,16 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, - } - op->op_notifier->n_user_token = args->user_token; - op->op_notifier->n_status = RDS_RDMA_SUCCESS; -+ -+ /* Enable rmda notification on data operation for composite -+ * rds messages and make sure notification is enabled only -+ * for the data operation which follows it so that application -+ * gets notified only after full message gets delivered. -+ */ -+ if (rm->data.op_sg) { -+ rm->rdma.op_notify = 0; -+ rm->data.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME); -+ } - } - - /* The cookie contains the R_Key of the remote memory region, and -diff --git a/net/rds/rds.h b/net/rds/rds.h -index 0e2797bdc316..4588860f4c3b 100644 ---- a/net/rds/rds.h -+++ b/net/rds/rds.h -@@ -378,6 +378,7 @@ struct rds_message { - } rdma; - struct rm_data_op { - unsigned int op_active:1; -+ unsigned int op_notify:1; - unsigned int op_nents; - unsigned int op_count; - unsigned int op_dmasg; -diff --git a/net/rds/send.c b/net/rds/send.c -index c9cdb358ea88..6815f03324d7 100644 ---- a/net/rds/send.c -+++ b/net/rds/send.c -@@ -467,12 +467,14 @@ void rds_rdma_send_complete(struct rds_message *rm, int status) - struct rm_rdma_op *ro; - struct rds_notifier *notifier; - unsigned long flags; -+ unsigned int notify = 0; - - spin_lock_irqsave(&rm->m_rs_lock, flags); - -+ notify = rm->rdma.op_notify | rm->data.op_notify; - ro = &rm->rdma; - if (test_bit(RDS_MSG_ON_SOCK, &rm->m_flags) && -- ro->op_active && ro->op_notify && ro->op_notifier) { -+ ro->op_active && notify && ro->op_notifier) { - notifier = ro->op_notifier; - rs = rm->m_rs; - sock_hold(rds_rs_to_sk(rs)); -diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c -index d3125c169684..065a69cf6118 100644 ---- a/sound/pci/au88x0/au88x0_core.c -+++ b/sound/pci/au88x0/au88x0_core.c -@@ -2279,6 +2279,9 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - } else { - int src[2], mix[2]; - -+ if (nr_ch < 1) -+ return -EINVAL; -+ - /* Get SRC and MIXER hardware resources. */ - for (i = 0; i < nr_ch; i++) { - if ((mix[i] = -diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c -index b8a256dfed7e..6a438a361592 100644 ---- a/sound/soc/soc-dapm.c -+++ b/sound/soc/soc-dapm.c -@@ -358,6 +358,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, - snd_soc_dapm_new_control_unlocked(widget->dapm, - &template); - kfree(name); -+ if (IS_ERR(data->widget)) { -+ ret = PTR_ERR(data->widget); -+ goto err_data; -+ } - if (!data->widget) { - ret = -ENOMEM; - goto err_data; -@@ -392,6 +396,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, - data->widget = snd_soc_dapm_new_control_unlocked( - widget->dapm, &template); - kfree(name); -+ if (IS_ERR(data->widget)) { -+ ret = PTR_ERR(data->widget); -+ goto err_data; -+ } - if (!data->widget) { - ret = -ENOMEM; - goto err_data; -@@ -3278,11 +3286,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, - - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); - w = snd_soc_dapm_new_control_unlocked(dapm, widget); -+ /* Do not nag about probe deferrals */ -+ if (IS_ERR(w)) { -+ int ret = PTR_ERR(w); -+ -+ if (ret != -EPROBE_DEFER) -+ dev_err(dapm->dev, -+ "ASoC: Failed to create DAPM control %s (%d)\n", -+ widget->name, ret); -+ goto out_unlock; -+ } - if (!w) - dev_err(dapm->dev, - "ASoC: Failed to create DAPM control %s\n", - widget->name); - -+out_unlock: - mutex_unlock(&dapm->card->dapm_mutex); - return w; - } -@@ -3304,6 +3323,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, - w->regulator = devm_regulator_get(dapm->dev, w->name); - if (IS_ERR(w->regulator)) { - ret = PTR_ERR(w->regulator); -+ if (ret == -EPROBE_DEFER) -+ return ERR_PTR(ret); - dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", - w->name, ret); - return NULL; -@@ -3322,6 +3343,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, - w->clk = devm_clk_get(dapm->dev, w->name); - if (IS_ERR(w->clk)) { - ret = PTR_ERR(w->clk); -+ if (ret == -EPROBE_DEFER) -+ return ERR_PTR(ret); - dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n", - w->name, ret); - return NULL; -@@ -3435,6 +3458,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, - mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); - for (i = 0; i < num; i++) { - w = snd_soc_dapm_new_control_unlocked(dapm, widget); -+ if (IS_ERR(w)) { -+ ret = PTR_ERR(w); -+ /* Do not nag about probe deferrals */ -+ if (ret == -EPROBE_DEFER) -+ break; -+ dev_err(dapm->dev, -+ "ASoC: Failed to create DAPM control %s (%d)\n", -+ widget->name, ret); -+ break; -+ } - if (!w) { - dev_err(dapm->dev, - "ASoC: Failed to create DAPM control %s\n", -@@ -3701,6 +3734,15 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, - dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name); - - w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template); -+ if (IS_ERR(w)) { -+ ret = PTR_ERR(w); -+ /* Do not nag about probe deferrals */ -+ if (ret != -EPROBE_DEFER) -+ dev_err(card->dev, -+ "ASoC: Failed to create %s widget (%d)\n", -+ link_name, ret); -+ goto outfree_kcontrol_news; -+ } - if (!w) { - dev_err(card->dev, "ASoC: Failed to create %s widget\n", - link_name); -@@ -3752,6 +3794,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, - template.name); - - w = snd_soc_dapm_new_control_unlocked(dapm, &template); -+ if (IS_ERR(w)) { -+ int ret = PTR_ERR(w); -+ -+ /* Do not nag about probe deferrals */ -+ if (ret != -EPROBE_DEFER) -+ dev_err(dapm->dev, -+ "ASoC: Failed to create %s widget (%d)\n", -+ dai->driver->playback.stream_name, ret); -+ return ret; -+ } - if (!w) { - dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", - dai->driver->playback.stream_name); -@@ -3771,6 +3823,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, - template.name); - - w = snd_soc_dapm_new_control_unlocked(dapm, &template); -+ if (IS_ERR(w)) { -+ int ret = PTR_ERR(w); -+ -+ /* Do not nag about probe deferrals */ -+ if (ret != -EPROBE_DEFER) -+ dev_err(dapm->dev, -+ "ASoC: Failed to create %s widget (%d)\n", -+ dai->driver->playback.stream_name, ret); -+ return ret; -+ } - if (!w) { - dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", - dai->driver->capture.stream_name); -diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c -index 70396d3f6472..e3f34a86413c 100644 ---- a/sound/soc/soc-topology.c -+++ b/sound/soc/soc-topology.c -@@ -1481,6 +1481,15 @@ widget: - widget = snd_soc_dapm_new_control(dapm, &template); - else - widget = snd_soc_dapm_new_control_unlocked(dapm, &template); -+ if (IS_ERR(widget)) { -+ ret = PTR_ERR(widget); -+ /* Do not nag about probe deferrals */ -+ if (ret != -EPROBE_DEFER) -+ dev_err(tplg->dev, -+ "ASoC: failed to create widget %s controls (%d)\n", -+ w->name, ret); -+ goto hdr_err; -+ } - if (widget == NULL) { - dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n", - w->name); diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.91-92.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.91-92.patch deleted file mode 100644 index 161f5253f..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.91-92.patch +++ /dev/null @@ -1,1905 +0,0 @@ -diff --git a/Makefile b/Makefile -index c1db50ef7fb5..fab2d640a27e 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 91 -+SUBLEVEL = 92 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/drivers/base/platform.c b/drivers/base/platform.c -index cb4ad6e98b28..065fcc4be263 100644 ---- a/drivers/base/platform.c -+++ b/drivers/base/platform.c -@@ -809,7 +809,8 @@ static ssize_t driver_override_store(struct device *dev, - struct platform_device *pdev = to_platform_device(dev); - char *driver_override, *old, *cp; - -- if (count > PATH_MAX) -+ /* We need to keep extra room for a newline */ -+ if (count >= (PAGE_SIZE - 1)) - return -EINVAL; - - driver_override = kstrndup(buf, count, GFP_KERNEL); -diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c -index d14bdc537587..0a2ac3efd04e 100644 ---- a/drivers/gpu/drm/i915/intel_bios.c -+++ b/drivers/gpu/drm/i915/intel_bios.c -@@ -957,6 +957,13 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, - is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; - is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); - -+ if (port == PORT_A && is_dvi) { -+ DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", -+ is_hdmi ? "/HDMI" : ""); -+ is_dvi = false; -+ is_hdmi = false; -+ } -+ - info->supports_dvi = is_dvi; - info->supports_hdmi = is_hdmi; - info->supports_dp = is_dp; -diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c -index d4d655a10df1..312aa1e33fb2 100644 ---- a/drivers/hid/i2c-hid/i2c-hid.c -+++ b/drivers/hid/i2c-hid/i2c-hid.c -@@ -540,7 +540,8 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) - { - /* the worst case is computed from the set_report command with a - * reportID > 15 and the maximum report length */ -- int args_len = sizeof(__u8) + /* optional ReportID byte */ -+ int args_len = sizeof(__u8) + /* ReportID */ -+ sizeof(__u8) + /* optional ReportID byte */ - sizeof(__u16) + /* data register */ - sizeof(__u16) + /* size of the report */ - report_size; /* report */ -diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c -index 1fb02dcbc500..12dcbd8226f2 100644 ---- a/drivers/hv/hv_fcopy.c -+++ b/drivers/hv/hv_fcopy.c -@@ -155,6 +155,10 @@ static void fcopy_send_data(struct work_struct *dummy) - out_src = smsg_out; - break; - -+ case WRITE_TO_FILE: -+ out_src = fcopy_transaction.fcopy_msg; -+ out_len = sizeof(struct hv_do_fcopy); -+ break; - default: - out_src = fcopy_transaction.fcopy_msg; - out_len = fcopy_transaction.recv_len; -diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c -index b6445d9e5453..d2dff159a471 100644 ---- a/drivers/hwtracing/stm/core.c -+++ b/drivers/hwtracing/stm/core.c -@@ -952,7 +952,7 @@ void stm_source_unregister_device(struct stm_source_data *data) - - stm_source_link_drop(src); - -- device_destroy(&stm_source_class, src->dev.devt); -+ device_unregister(&src->dev); - } - EXPORT_SYMBOL_GPL(stm_source_unregister_device); - -diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c -index 4d960d3b93c0..91d34ed756ea 100644 ---- a/drivers/iio/adc/ad7793.c -+++ b/drivers/iio/adc/ad7793.c -@@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, - unsigned int vref_mv) - { - struct ad7793_state *st = iio_priv(indio_dev); -- int i, ret = -1; -+ int i, ret; - unsigned long long scale_uv; - u32 id; - -@@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, - return ret; - - /* reset the serial interface */ -- ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); -+ ret = ad_sd_reset(&st->sd, 32); - if (ret < 0) - goto out; - usleep_range(500, 2000); /* Wait for at least 500us */ -diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c -index d10bd0c97233..22c4c17cd996 100644 ---- a/drivers/iio/adc/ad_sigma_delta.c -+++ b/drivers/iio/adc/ad_sigma_delta.c -@@ -177,6 +177,34 @@ out: - } - EXPORT_SYMBOL_GPL(ad_sd_read_reg); - -+/** -+ * ad_sd_reset() - Reset the serial interface -+ * -+ * @sigma_delta: The sigma delta device -+ * @reset_length: Number of SCLKs with DIN = 1 -+ * -+ * Returns 0 on success, an error code otherwise. -+ **/ -+int ad_sd_reset(struct ad_sigma_delta *sigma_delta, -+ unsigned int reset_length) -+{ -+ uint8_t *buf; -+ unsigned int size; -+ int ret; -+ -+ size = DIV_ROUND_UP(reset_length, 8); -+ buf = kcalloc(size, sizeof(*buf), GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ memset(buf, 0xff, size); -+ ret = spi_write(sigma_delta->spi, buf, size); -+ kfree(buf); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(ad_sd_reset); -+ - static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, - unsigned int mode, unsigned int channel) - { -diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c -index 8569c8e1f4b2..ad2681acce9a 100644 ---- a/drivers/iio/adc/mcp320x.c -+++ b/drivers/iio/adc/mcp320x.c -@@ -17,6 +17,8 @@ - * MCP3204 - * MCP3208 - * ------------ -+ * 13 bit converter -+ * MCP3301 - * - * Datasheet can be found here: - * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 -@@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index, - } - - static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, -- bool differential, int device_index) -+ bool differential, int device_index, int *val) - { - int ret; - -@@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, - - switch (device_index) { - case mcp3001: -- return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); -+ *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); -+ return 0; - case mcp3002: - case mcp3004: - case mcp3008: -- return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); -+ *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); -+ return 0; - case mcp3201: -- return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); -+ *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); -+ return 0; - case mcp3202: - case mcp3204: - case mcp3208: -- return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); -+ *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); -+ return 0; - case mcp3301: -- return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12); -+ *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8 -+ | adc->rx_buf[1], 12); -+ return 0; - default: - return -EINVAL; - } -@@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev, - switch (mask) { - case IIO_CHAN_INFO_RAW: - ret = mcp320x_adc_conversion(adc, channel->address, -- channel->differential, device_index); -- -+ channel->differential, device_index, val); - if (ret < 0) - goto out; - -- *val = ret; - ret = IIO_VAL_INT; - break; - -@@ -304,6 +310,7 @@ static int mcp320x_probe(struct spi_device *spi) - indio_dev->name = spi_get_device_id(spi)->name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &mcp320x_info; -+ spi_set_drvdata(spi, indio_dev); - - chip_info = &mcp320x_chip_infos[spi_get_device_id(spi)->driver_data]; - indio_dev->channels = chip_info->channels; -diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c -index 0c74869a540a..7ffc5db4d7ee 100644 ---- a/drivers/iio/adc/twl4030-madc.c -+++ b/drivers/iio/adc/twl4030-madc.c -@@ -866,8 +866,10 @@ static int twl4030_madc_probe(struct platform_device *pdev) - - /* Enable 3v1 bias regulator for MADC[3:6] */ - madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1"); -- if (IS_ERR(madc->usb3v1)) -- return -ENODEV; -+ if (IS_ERR(madc->usb3v1)) { -+ ret = -ENODEV; -+ goto err_i2c; -+ } - - ret = regulator_enable(madc->usb3v1); - if (ret) -@@ -876,11 +878,13 @@ static int twl4030_madc_probe(struct platform_device *pdev) - ret = iio_device_register(iio_dev); - if (ret) { - dev_err(&pdev->dev, "could not register iio device\n"); -- goto err_i2c; -+ goto err_usb3v1; - } - - return 0; - -+err_usb3v1: -+ regulator_disable(madc->usb3v1); - err_i2c: - twl4030_madc_set_current_generator(madc, 0, 0); - err_current_generator: -diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c -index 131b434af994..e08a3c794120 100644 ---- a/drivers/iio/industrialio-core.c -+++ b/drivers/iio/industrialio-core.c -@@ -221,8 +221,10 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, - ret = indio_dev->info->debugfs_reg_access(indio_dev, - indio_dev->cached_reg_addr, - 0, &val); -- if (ret) -+ if (ret) { - dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); -+ return ret; -+ } - - len = snprintf(buf, sizeof(buf), "0x%X\n", val); - -diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c -index c2ea4e5666fb..9710cf71054a 100644 ---- a/drivers/net/usb/usbnet.c -+++ b/drivers/net/usb/usbnet.c -@@ -1990,6 +1990,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, - elength = 1; - goto next_desc; - } -+ if ((buflen < elength) || (elength < 3)) { -+ dev_err(&intf->dev, "invalid descriptor buffer length\n"); -+ break; -+ } - if (buffer[1] != USB_DT_CS_INTERFACE) { - dev_err(&intf->dev, "skipping garbage\n"); - goto next_desc; -diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -index da5826d788d6..f18491cf793c 100644 ---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -@@ -876,7 +876,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, - - eth_broadcast_addr(params_le->bssid); - params_le->bss_type = DOT11_BSSTYPE_ANY; -- params_le->scan_type = 0; -+ params_le->scan_type = BRCMF_SCANTYPE_ACTIVE; - params_le->channel_num = 0; - params_le->nprobes = cpu_to_le32(-1); - params_le->active_time = cpu_to_le32(-1); -@@ -884,12 +884,9 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, - params_le->home_time = cpu_to_le32(-1); - memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le)); - -- /* if request is null exit so it will be all channel broadcast scan */ -- if (!request) -- return; -- - n_ssids = request->n_ssids; - n_channels = request->n_channels; -+ - /* Copy channel array if applicable */ - brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n", - n_channels); -@@ -926,16 +923,8 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, - ptr += sizeof(ssid_le); - } - } else { -- brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids); -- if ((request->ssids) && request->ssids->ssid_len) { -- brcmf_dbg(SCAN, "SSID %s len=%d\n", -- params_le->ssid_le.SSID, -- request->ssids->ssid_len); -- params_le->ssid_le.SSID_len = -- cpu_to_le32(request->ssids->ssid_len); -- memcpy(¶ms_le->ssid_le.SSID, request->ssids->ssid, -- request->ssids->ssid_len); -- } -+ brcmf_dbg(SCAN, "Performing passive scan\n"); -+ params_le->scan_type = BRCMF_SCANTYPE_PASSIVE; - } - /* Adding mask to channel numbers */ - params_le->channel_num = -diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h -index daa427b46712..4320c4cae53e 100644 ---- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h -+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h -@@ -45,6 +45,11 @@ - #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff - #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 - -+/* scan type definitions */ -+#define BRCMF_SCANTYPE_DEFAULT 0xFF -+#define BRCMF_SCANTYPE_ACTIVE 0 -+#define BRCMF_SCANTYPE_PASSIVE 1 -+ - /* primary (ie tx) key */ - #define BRCMF_PRIMARY_KEY (1 << 1) - #define DOT11_BSSTYPE_ANY 2 -diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c -index d82984912e04..95b82cc132e6 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c -+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c -@@ -73,6 +73,7 @@ - /* NVM offsets (in words) definitions */ - enum wkp_nvm_offsets { - /* NVM HW-Section offset (in words) definitions */ -+ SUBSYSTEM_ID = 0x0A, - HW_ADDR = 0x15, - - /* NVM SW-Section offset (in words) definitions */ -@@ -257,13 +258,12 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, - static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, - struct iwl_nvm_data *data, - const __le16 * const nvm_ch_flags, -- bool lar_supported) -+ bool lar_supported, bool no_wide_in_5ghz) - { - int ch_idx; - int n_channels = 0; - struct ieee80211_channel *channel; - u16 ch_flags; -- bool is_5ghz; - int num_of_ch, num_2ghz_channels; - const u8 *nvm_chan; - -@@ -278,12 +278,20 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, - } - - for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { -+ bool is_5ghz = (ch_idx >= num_2ghz_channels); -+ - ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); - -- if (ch_idx >= num_2ghz_channels && -- !data->sku_cap_band_52GHz_enable) -+ if (is_5ghz && !data->sku_cap_band_52GHz_enable) - continue; - -+ /* workaround to disable wide channels in 5GHz */ -+ if (no_wide_in_5ghz && is_5ghz) { -+ ch_flags &= ~(NVM_CHANNEL_40MHZ | -+ NVM_CHANNEL_80MHZ | -+ NVM_CHANNEL_160MHZ); -+ } -+ - if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID)) { - /* - * Channels might become valid later if lar is -@@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, - n_channels++; - - channel->hw_value = nvm_chan[ch_idx]; -- channel->band = (ch_idx < num_2ghz_channels) ? -- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; -+ channel->band = is_5ghz ? -+ IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; - channel->center_freq = - ieee80211_channel_to_frequency( - channel->hw_value, channel->band); -@@ -316,7 +324,6 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, - * is not used in mvm, and is used for backwards compatibility - */ - channel->max_power = IWL_DEFAULT_MAX_TX_POWER; -- is_5ghz = channel->band == IEEE80211_BAND_5GHZ; - - /* don't put limitations in case we're using LAR */ - if (!lar_supported) -@@ -405,7 +412,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, - static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, - struct iwl_nvm_data *data, - const __le16 *ch_section, -- u8 tx_chains, u8 rx_chains, bool lar_supported) -+ u8 tx_chains, u8 rx_chains, bool lar_supported, -+ bool no_wide_in_5ghz) - { - int n_channels; - int n_used = 0; -@@ -414,12 +422,14 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, - if (cfg->device_family != IWL_DEVICE_FAMILY_8000) - n_channels = iwl_init_channel_map( - dev, cfg, data, -- &ch_section[NVM_CHANNELS], lar_supported); -+ &ch_section[NVM_CHANNELS], lar_supported, -+ no_wide_in_5ghz); - else - n_channels = iwl_init_channel_map( - dev, cfg, data, - &ch_section[NVM_CHANNELS_FAMILY_8000], -- lar_supported); -+ lar_supported, -+ no_wide_in_5ghz); - - sband = &data->bands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; -@@ -582,6 +592,39 @@ static void iwl_set_hw_address_family_8000(struct device *dev, - - #define IWL_4165_DEVICE_ID 0x5501 - -+static bool -+iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg, -+ const __le16 *nvm_hw) -+{ -+ /* -+ * Workaround a bug in Indonesia SKUs where the regulatory in -+ * some 7000-family OTPs erroneously allow wide channels in -+ * 5GHz. To check for Indonesia, we take the SKU value from -+ * bits 1-4 in the subsystem ID and check if it is either 5 or -+ * 9. In those cases, we need to force-disable wide channels -+ * in 5GHz otherwise the FW will throw a sysassert when we try -+ * to use them. -+ */ -+ if (cfg->device_family == IWL_DEVICE_FAMILY_7000) { -+ /* -+ * Unlike the other sections in the NVM, the hw -+ * section uses big-endian. -+ */ -+ u16 subsystem_id = be16_to_cpup((const __be16 *)nvm_hw -+ + SUBSYSTEM_ID); -+ u8 sku = (subsystem_id & 0x1e) >> 1; -+ -+ if (sku == 5 || sku == 9) { -+ IWL_DEBUG_EEPROM(dev, -+ "disabling wide channels in 5GHz (0x%0x %d)\n", -+ subsystem_id, sku); -+ return true; -+ } -+ } -+ -+ return false; -+} -+ - struct iwl_nvm_data * - iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, - const __le16 *nvm_hw, const __le16 *nvm_sw, -@@ -591,6 +634,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, - u32 mac_addr0, u32 mac_addr1, u32 hw_id) - { - struct iwl_nvm_data *data; -+ bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw); - u32 sku; - u32 radio_cfg; - u16 lar_config; -@@ -657,7 +701,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, - iwl_set_hw_address(cfg, data, nvm_hw); - - iwl_init_sbands(dev, cfg, data, nvm_sw, -- tx_chains, rx_chains, lar_fw_supported); -+ tx_chains, rx_chains, lar_fw_supported, -+ no_wide_in_5ghz); - } else { - u16 lar_offset = data->nvm_version < 0xE39 ? - NVM_LAR_OFFSET_FAMILY_8000_OLD : -@@ -673,7 +718,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, - - iwl_init_sbands(dev, cfg, data, regulatory, - tx_chains, rx_chains, -- lar_fw_supported && data->lar_enabled); -+ lar_fw_supported && data->lar_enabled, -+ no_wide_in_5ghz); - } - - data->calib_version = 255; -diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h -index b8a5a8e8f57d..88cf4f5025b0 100644 ---- a/drivers/nvme/host/nvme.h -+++ b/drivers/nvme/host/nvme.h -@@ -14,6 +14,7 @@ - #ifndef _NVME_H - #define _NVME_H - -+#include - #include - #include - #include -@@ -62,6 +63,7 @@ struct nvme_dev { - struct work_struct reset_work; - struct work_struct probe_work; - struct work_struct scan_work; -+ struct mutex shutdown_lock; - char name[12]; - char serial[20]; - char model[40]; -diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c -index 4c673d45f1bd..669edbd47602 100644 ---- a/drivers/nvme/host/pci.c -+++ b/drivers/nvme/host/pci.c -@@ -2954,6 +2954,7 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) - - nvme_dev_list_remove(dev); - -+ mutex_lock(&dev->shutdown_lock); - if (pci_is_enabled(to_pci_dev(dev->dev))) { - nvme_freeze_queues(dev); - csts = readl(&dev->bar->csts); -@@ -2972,6 +2973,7 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) - - for (i = dev->queue_count - 1; i >= 0; i--) - nvme_clear_queue(dev->queues[i]); -+ mutex_unlock(&dev->shutdown_lock); - } - - static void nvme_dev_remove(struct nvme_dev *dev) -@@ -3328,6 +3330,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) - - INIT_LIST_HEAD(&dev->namespaces); - INIT_WORK(&dev->reset_work, nvme_reset_work); -+ mutex_init(&dev->shutdown_lock); - dev->dev = get_device(&pdev->dev); - pci_set_drvdata(pdev, dev); - -diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c -index 8750c86f95f9..7e1681cf287c 100644 ---- a/drivers/scsi/sd.c -+++ b/drivers/scsi/sd.c -@@ -2878,8 +2878,6 @@ static int sd_revalidate_disk(struct gendisk *disk) - sd_read_write_same(sdkp, buffer); - } - -- sdkp->first_scan = 0; -- - /* - * We now have all cache related info, determine how we deal - * with flush requests. -@@ -2894,7 +2892,7 @@ static int sd_revalidate_disk(struct gendisk *disk) - q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); - - /* -- * Use the device's preferred I/O size for reads and writes -+ * Determine the device's preferred I/O size for reads and writes - * unless the reported value is unreasonably small, large, or - * garbage. - */ -@@ -2908,8 +2906,19 @@ static int sd_revalidate_disk(struct gendisk *disk) - rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), - (sector_t)BLK_DEF_MAX_SECTORS); - -- /* Combine with controller limits */ -- q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q)); -+ /* Do not exceed controller limit */ -+ rw_max = min(rw_max, queue_max_hw_sectors(q)); -+ -+ /* -+ * Only update max_sectors if previously unset or if the current value -+ * exceeds the capabilities of the hardware. -+ */ -+ if (sdkp->first_scan || -+ q->limits.max_sectors > q->limits.max_dev_sectors || -+ q->limits.max_sectors > q->limits.max_hw_sectors) -+ q->limits.max_sectors = rw_max; -+ -+ sdkp->first_scan = 0; - - set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity)); - sd_config_write_same(sdkp); -diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c -index 20314ff08be0..abc66908681d 100644 ---- a/drivers/staging/iio/adc/ad7192.c -+++ b/drivers/staging/iio/adc/ad7192.c -@@ -205,11 +205,9 @@ static int ad7192_setup(struct ad7192_state *st, - struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); - unsigned long long scale_uv; - int i, ret, id; -- u8 ones[6]; - - /* reset the serial interface */ -- memset(&ones, 0xFF, 6); -- ret = spi_write(st->sd.spi, &ones, 6); -+ ret = ad_sd_reset(&st->sd, 48); - if (ret < 0) - goto out; - usleep_range(500, 1000); /* Wait for at least 500us */ -diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c -index 325cbc9c35d8..d9d048fc9082 100644 ---- a/drivers/usb/core/config.c -+++ b/drivers/usb/core/config.c -@@ -609,15 +609,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, - - } else if (header->bDescriptorType == - USB_DT_INTERFACE_ASSOCIATION) { -+ struct usb_interface_assoc_descriptor *d; -+ -+ d = (struct usb_interface_assoc_descriptor *)header; -+ if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { -+ dev_warn(ddev, -+ "config %d has an invalid interface association descriptor of length %d, skipping\n", -+ cfgno, d->bLength); -+ continue; -+ } -+ - if (iad_num == USB_MAXIADS) { - dev_warn(ddev, "found more Interface " - "Association Descriptors " - "than allocated for in " - "configuration %d\n", cfgno); - } else { -- config->intf_assoc[iad_num] = -- (struct usb_interface_assoc_descriptor -- *)header; -+ config->intf_assoc[iad_num] = d; - iad_num++; - } - -@@ -818,7 +826,7 @@ int usb_get_configuration(struct usb_device *dev) - } - - if (dev->quirks & USB_QUIRK_DELAY_INIT) -- msleep(100); -+ msleep(200); - - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, - bigbuffer, length); -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index 873ba02d59e6..bd9419213d06 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -1417,7 +1417,11 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb - totlen += isopkt[u].length; - } - u *= sizeof(struct usb_iso_packet_descriptor); -- uurb->buffer_length = totlen; -+ if (totlen <= uurb->buffer_length) -+ uurb->buffer_length = totlen; -+ else -+ WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d", -+ totlen, uurb->buffer_length); - break; - - default: -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index cdf4be3939f5..51bba58c0c3b 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -4761,7 +4761,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, - goto loop; - - if (udev->quirks & USB_QUIRK_DELAY_INIT) -- msleep(1000); -+ msleep(2000); - - /* consecutive bus-powered hubs aren't reliable; they can - * violate the voltage drop budget. if the new child has -diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c -index a069726da72a..4dd3c7672247 100644 ---- a/drivers/usb/gadget/function/f_mass_storage.c -+++ b/drivers/usb/gadget/function/f_mass_storage.c -@@ -306,8 +306,6 @@ struct fsg_common { - struct completion thread_notifier; - struct task_struct *thread_task; - -- /* Callback functions. */ -- const struct fsg_operations *ops; - /* Gadget's private data. */ - void *private_data; - -@@ -2504,6 +2502,7 @@ static void handle_exception(struct fsg_common *common) - static int fsg_main_thread(void *common_) - { - struct fsg_common *common = common_; -+ int i; - - /* - * Allow the thread to be killed by a signal, but set the signal mask -@@ -2565,21 +2564,16 @@ static int fsg_main_thread(void *common_) - common->thread_task = NULL; - spin_unlock_irq(&common->lock); - -- if (!common->ops || !common->ops->thread_exits -- || common->ops->thread_exits(common) < 0) { -- int i; -+ /* Eject media from all LUNs */ - -- down_write(&common->filesem); -- for (i = 0; i < ARRAY_SIZE(common->luns); --i) { -- struct fsg_lun *curlun = common->luns[i]; -- if (!curlun || !fsg_lun_is_open(curlun)) -- continue; -+ down_write(&common->filesem); -+ for (i = 0; i < ARRAY_SIZE(common->luns); i++) { -+ struct fsg_lun *curlun = common->luns[i]; - -+ if (curlun && fsg_lun_is_open(curlun)) - fsg_lun_close(curlun); -- curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; -- } -- up_write(&common->filesem); - } -+ up_write(&common->filesem); - - /* Let fsg_unbind() know the thread has exited */ - complete_and_exit(&common->thread_notifier, 0); -@@ -2785,13 +2779,6 @@ void fsg_common_remove_luns(struct fsg_common *common) - } - EXPORT_SYMBOL_GPL(fsg_common_remove_luns); - --void fsg_common_set_ops(struct fsg_common *common, -- const struct fsg_operations *ops) --{ -- common->ops = ops; --} --EXPORT_SYMBOL_GPL(fsg_common_set_ops); -- - void fsg_common_free_buffers(struct fsg_common *common) - { - _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); -diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h -index b6a9918eaefb..dfa2176f43c2 100644 ---- a/drivers/usb/gadget/function/f_mass_storage.h -+++ b/drivers/usb/gadget/function/f_mass_storage.h -@@ -60,17 +60,6 @@ struct fsg_module_parameters { - struct fsg_common; - - /* FSF callback functions */ --struct fsg_operations { -- /* -- * Callback function to call when thread exits. If no -- * callback is set or it returns value lower then zero MSF -- * will force eject all LUNs it operates on (including those -- * marked as non-removable or with prevent_medium_removal flag -- * set). -- */ -- int (*thread_exits)(struct fsg_common *common); --}; -- - struct fsg_lun_opts { - struct config_group group; - struct fsg_lun *lun; -@@ -141,9 +130,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun); - - void fsg_common_remove_luns(struct fsg_common *common); - --void fsg_common_set_ops(struct fsg_common *common, -- const struct fsg_operations *ops); -- - int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, - unsigned int id, const char *name, - const char **name_pfx); -diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c -index 43ce2cfcdb4d..b6df47aa25af 100644 ---- a/drivers/usb/gadget/legacy/inode.c -+++ b/drivers/usb/gadget/legacy/inode.c -@@ -27,7 +27,7 @@ - #include - #include - #include -- -+#include - #include - #include - -@@ -116,6 +116,7 @@ enum ep0_state { - struct dev_data { - spinlock_t lock; - atomic_t count; -+ int udc_usage; - enum ep0_state state; /* P: lock */ - struct usb_gadgetfs_event event [N_EVENT]; - unsigned ev_next; -@@ -512,9 +513,9 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) - INIT_WORK(&priv->work, ep_user_copy_worker); - schedule_work(&priv->work); - } -- spin_unlock(&epdata->dev->lock); - - usb_ep_free_request(ep, req); -+ spin_unlock(&epdata->dev->lock); - put_ep(epdata); - } - -@@ -938,9 +939,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) - struct usb_request *req = dev->req; - - if ((retval = setup_req (ep, req, 0)) == 0) { -+ ++dev->udc_usage; - spin_unlock_irq (&dev->lock); - retval = usb_ep_queue (ep, req, GFP_KERNEL); - spin_lock_irq (&dev->lock); -+ --dev->udc_usage; - } - dev->state = STATE_DEV_CONNECTED; - -@@ -982,11 +985,14 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) - retval = -EIO; - else { - len = min (len, (size_t)dev->req->actual); --// FIXME don't call this with the spinlock held ... -+ ++dev->udc_usage; -+ spin_unlock_irq(&dev->lock); - if (copy_to_user (buf, dev->req->buf, len)) - retval = -EFAULT; - else - retval = len; -+ spin_lock_irq(&dev->lock); -+ --dev->udc_usage; - clean_req (dev->gadget->ep0, dev->req); - /* NOTE userspace can't yet choose to stall */ - } -@@ -1130,6 +1136,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) - retval = setup_req (dev->gadget->ep0, dev->req, len); - if (retval == 0) { - dev->state = STATE_DEV_CONNECTED; -+ ++dev->udc_usage; - spin_unlock_irq (&dev->lock); - if (copy_from_user (dev->req->buf, buf, len)) - retval = -EFAULT; -@@ -1140,10 +1147,10 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) - dev->gadget->ep0, dev->req, - GFP_KERNEL); - } -+ spin_lock_irq(&dev->lock); -+ --dev->udc_usage; - if (retval < 0) { -- spin_lock_irq (&dev->lock); - clean_req (dev->gadget->ep0, dev->req); -- spin_unlock_irq (&dev->lock); - } else - retval = len; - -@@ -1240,9 +1247,21 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) - struct usb_gadget *gadget = dev->gadget; - long ret = -ENOTTY; - -- if (gadget->ops->ioctl) -+ spin_lock_irq(&dev->lock); -+ if (dev->state == STATE_DEV_OPENED || -+ dev->state == STATE_DEV_UNBOUND) { -+ /* Not bound to a UDC */ -+ } else if (gadget->ops->ioctl) { -+ ++dev->udc_usage; -+ spin_unlock_irq(&dev->lock); -+ - ret = gadget->ops->ioctl (gadget, code, value); - -+ spin_lock_irq(&dev->lock); -+ --dev->udc_usage; -+ } -+ spin_unlock_irq(&dev->lock); -+ - return ret; - } - -@@ -1460,10 +1479,12 @@ delegate: - if (value < 0) - break; - -+ ++dev->udc_usage; - spin_unlock (&dev->lock); - value = usb_ep_queue (gadget->ep0, dev->req, - GFP_KERNEL); - spin_lock (&dev->lock); -+ --dev->udc_usage; - if (value < 0) { - clean_req (gadget->ep0, dev->req); - break; -@@ -1487,8 +1508,12 @@ delegate: - req->length = value; - req->zero = value < w_length; - -+ ++dev->udc_usage; - spin_unlock (&dev->lock); - value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL); -+ spin_lock(&dev->lock); -+ --dev->udc_usage; -+ spin_unlock(&dev->lock); - if (value < 0) { - DBG (dev, "ep_queue --> %d\n", value); - req->status = 0; -@@ -1515,21 +1540,24 @@ static void destroy_ep_files (struct dev_data *dev) - /* break link to FS */ - ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles); - list_del_init (&ep->epfiles); -+ spin_unlock_irq (&dev->lock); -+ - dentry = ep->dentry; - ep->dentry = NULL; - parent = d_inode(dentry->d_parent); - - /* break link to controller */ -+ mutex_lock(&ep->lock); - if (ep->state == STATE_EP_ENABLED) - (void) usb_ep_disable (ep->ep); - ep->state = STATE_EP_UNBOUND; - usb_ep_free_request (ep->ep, ep->req); - ep->ep = NULL; -+ mutex_unlock(&ep->lock); -+ - wake_up (&ep->wait); - put_ep (ep); - -- spin_unlock_irq (&dev->lock); -- - /* break link to dcache */ - mutex_lock (&parent->i_mutex); - d_delete (dentry); -@@ -1600,6 +1628,11 @@ gadgetfs_unbind (struct usb_gadget *gadget) - - spin_lock_irq (&dev->lock); - dev->state = STATE_DEV_UNBOUND; -+ while (dev->udc_usage > 0) { -+ spin_unlock_irq(&dev->lock); -+ usleep_range(1000, 2000); -+ spin_lock_irq(&dev->lock); -+ } - spin_unlock_irq (&dev->lock); - - destroy_ep_files (dev); -diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c -index 99aa22c81770..b0099d7c3886 100644 ---- a/drivers/usb/gadget/legacy/mass_storage.c -+++ b/drivers/usb/gadget/legacy/mass_storage.c -@@ -107,15 +107,6 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; - - FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); - --static unsigned long msg_registered; --static void msg_cleanup(void); -- --static int msg_thread_exits(struct fsg_common *common) --{ -- msg_cleanup(); -- return 0; --} -- - static int msg_do_config(struct usb_configuration *c) - { - struct fsg_opts *opts; -@@ -154,9 +145,6 @@ static struct usb_configuration msg_config_driver = { - - static int msg_bind(struct usb_composite_dev *cdev) - { -- static const struct fsg_operations ops = { -- .thread_exits = msg_thread_exits, -- }; - struct fsg_opts *opts; - struct fsg_config config; - int status; -@@ -173,8 +161,6 @@ static int msg_bind(struct usb_composite_dev *cdev) - if (status) - goto fail; - -- fsg_common_set_ops(opts->common, &ops); -- - status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); - if (status) - goto fail_set_cdev; -@@ -210,7 +196,6 @@ static int msg_bind(struct usb_composite_dev *cdev) - usb_composite_overwrite_options(cdev, &coverwrite); - dev_info(&cdev->gadget->dev, - DRIVER_DESC ", version: " DRIVER_VERSION "\n"); -- set_bit(0, &msg_registered); - return 0; - - fail_otg_desc: -@@ -261,9 +246,8 @@ static int __init msg_init(void) - } - module_init(msg_init); - --static void msg_cleanup(void) -+static void __exit msg_cleanup(void) - { -- if (test_and_clear_bit(0, &msg_registered)) -- usb_composite_unregister(&msg_driver); -+ usb_composite_unregister(&msg_driver); - } - module_exit(msg_cleanup); -diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c -index f92f5aff0dd5..585cb8734f50 100644 ---- a/drivers/usb/gadget/udc/atmel_usba_udc.c -+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c -@@ -28,6 +28,8 @@ - #include - - #include "atmel_usba_udc.h" -+#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \ -+ | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING) - - #ifdef CONFIG_USB_GADGET_DEBUG_FS - #include -@@ -2185,7 +2187,7 @@ static int usba_udc_probe(struct platform_device *pdev) - IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(&pdev->dev, - gpio_to_irq(udc->vbus_pin), NULL, -- usba_vbus_irq_thread, IRQF_ONESHOT, -+ usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, - "atmel_usba_udc", udc); - if (ret) { - udc->vbus_pin = -ENODEV; -diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c -index 64f404a1a072..db645c38055d 100644 ---- a/drivers/usb/gadget/udc/dummy_hcd.c -+++ b/drivers/usb/gadget/udc/dummy_hcd.c -@@ -237,6 +237,8 @@ struct dummy_hcd { - - struct usb_device *udev; - struct list_head urbp_list; -+ struct urbp *next_frame_urbp; -+ - u32 stream_en_ep; - u8 num_stream[30 / 2]; - -@@ -253,11 +255,13 @@ struct dummy { - */ - struct dummy_ep ep[DUMMY_ENDPOINTS]; - int address; -+ int callback_usage; - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - struct dummy_request fifo_req; - u8 fifo_buf[FIFO_SIZE]; - u16 devstatus; -+ unsigned ints_enabled:1; - unsigned udc_suspended:1; - unsigned pullup:1; - -@@ -440,18 +444,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd) - (~dum_hcd->old_status) & dum_hcd->port_status; - - /* Report reset and disconnect events to the driver */ -- if (dum->driver && (disconnect || reset)) { -+ if (dum->ints_enabled && (disconnect || reset)) { - stop_activity(dum); -+ ++dum->callback_usage; -+ spin_unlock(&dum->lock); - if (reset) - usb_gadget_udc_reset(&dum->gadget, dum->driver); - else - dum->driver->disconnect(&dum->gadget); -+ spin_lock(&dum->lock); -+ --dum->callback_usage; - } -- } else if (dum_hcd->active != dum_hcd->old_active) { -+ } else if (dum_hcd->active != dum_hcd->old_active && -+ dum->ints_enabled) { -+ ++dum->callback_usage; -+ spin_unlock(&dum->lock); - if (dum_hcd->old_active && dum->driver->suspend) - dum->driver->suspend(&dum->gadget); - else if (!dum_hcd->old_active && dum->driver->resume) - dum->driver->resume(&dum->gadget); -+ spin_lock(&dum->lock); -+ --dum->callback_usage; - } - - dum_hcd->old_status = dum_hcd->port_status; -@@ -967,8 +980,11 @@ static int dummy_udc_start(struct usb_gadget *g, - * can't enumerate without help from the driver we're binding. - */ - -+ spin_lock_irq(&dum->lock); - dum->devstatus = 0; - dum->driver = driver; -+ dum->ints_enabled = 1; -+ spin_unlock_irq(&dum->lock); - - return 0; - } -@@ -979,6 +995,16 @@ static int dummy_udc_stop(struct usb_gadget *g) - struct dummy *dum = dum_hcd->dum; - - spin_lock_irq(&dum->lock); -+ dum->ints_enabled = 0; -+ stop_activity(dum); -+ -+ /* emulate synchronize_irq(): wait for callbacks to finish */ -+ while (dum->callback_usage > 0) { -+ spin_unlock_irq(&dum->lock); -+ usleep_range(1000, 2000); -+ spin_lock_irq(&dum->lock); -+ } -+ - dum->driver = NULL; - spin_unlock_irq(&dum->lock); - -@@ -1032,7 +1058,12 @@ static int dummy_udc_probe(struct platform_device *pdev) - memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); - dum->gadget.name = gadget_name; - dum->gadget.ops = &dummy_ops; -- dum->gadget.max_speed = USB_SPEED_SUPER; -+ if (mod_data.is_super_speed) -+ dum->gadget.max_speed = USB_SPEED_SUPER; -+ else if (mod_data.is_high_speed) -+ dum->gadget.max_speed = USB_SPEED_HIGH; -+ else -+ dum->gadget.max_speed = USB_SPEED_FULL; - - dum->gadget.dev.parent = &pdev->dev; - init_dummy_udc_hw(dum); -@@ -1241,6 +1272,8 @@ static int dummy_urb_enqueue( - - list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); - urb->hcpriv = urbp; -+ if (!dum_hcd->next_frame_urbp) -+ dum_hcd->next_frame_urbp = urbp; - if (usb_pipetype(urb->pipe) == PIPE_CONTROL) - urb->error_count = 1; /* mark as a new urb */ - -@@ -1517,6 +1550,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address) - if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? - dum->ss_hcd : dum->hs_hcd))) - return NULL; -+ if (!dum->ints_enabled) -+ return NULL; - if ((address & ~USB_DIR_IN) == 0) - return &dum->ep[0]; - for (i = 1; i < DUMMY_ENDPOINTS; i++) { -@@ -1758,6 +1793,7 @@ static void dummy_timer(unsigned long _dum_hcd) - spin_unlock_irqrestore(&dum->lock, flags); - return; - } -+ dum_hcd->next_frame_urbp = NULL; - - for (i = 0; i < DUMMY_ENDPOINTS; i++) { - if (!ep_info[i].name) -@@ -1774,6 +1810,10 @@ restart: - int type; - int status = -EINPROGRESS; - -+ /* stop when we reach URBs queued after the timer interrupt */ -+ if (urbp == dum_hcd->next_frame_urbp) -+ break; -+ - urb = urbp->urb; - if (urb->unlinked) - goto return_urb; -@@ -1853,10 +1893,12 @@ restart: - * until setup() returns; no reentrancy issues etc. - */ - if (value > 0) { -+ ++dum->callback_usage; - spin_unlock(&dum->lock); - value = dum->driver->setup(&dum->gadget, - &setup); - spin_lock(&dum->lock); -+ --dum->callback_usage; - - if (value >= 0) { - /* no delays (max 64KB data stage) */ -@@ -2564,8 +2606,6 @@ static struct hc_driver dummy_hcd = { - .product_desc = "Dummy host controller", - .hcd_priv_size = sizeof(struct dummy_hcd), - -- .flags = HCD_USB3 | HCD_SHARED, -- - .reset = dummy_setup, - .start = dummy_start, - .stop = dummy_stop, -@@ -2594,8 +2634,12 @@ static int dummy_hcd_probe(struct platform_device *pdev) - dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); - dum = *((void **)dev_get_platdata(&pdev->dev)); - -- if (!mod_data.is_super_speed) -+ if (mod_data.is_super_speed) -+ dummy_hcd.flags = HCD_USB3 | HCD_SHARED; -+ else if (mod_data.is_high_speed) - dummy_hcd.flags = HCD_USB2; -+ else -+ dummy_hcd.flags = HCD_USB11; - hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); - if (!hs_hcd) - return -ENOMEM; -diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c -index 1fc6f478a02c..89e9494c3245 100644 ---- a/drivers/usb/host/pci-quirks.c -+++ b/drivers/usb/host/pci-quirks.c -@@ -969,7 +969,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); - * - * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. - * It signals to the BIOS that the OS wants control of the host controller, -- * and then waits 5 seconds for the BIOS to hand over control. -+ * and then waits 1 second for the BIOS to hand over control. - * If we timeout, assume the BIOS is broken and take control anyway. - */ - static void quirk_usb_handoff_xhci(struct pci_dev *pdev) -@@ -1015,9 +1015,9 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) - if (val & XHCI_HC_BIOS_OWNED) { - writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); - -- /* Wait for 5 seconds with 10 microsecond polling interval */ -+ /* Wait for 1 second with 10 microsecond polling interval */ - timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, -- 0, 5000, 10); -+ 0, 1000000, 10); - - /* Assume a buggy BIOS and take HC ownership anyway */ - if (timeout) { -@@ -1046,7 +1046,7 @@ hc_init: - * operational or runtime registers. Wait 5 seconds and no more. - */ - timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, -- 5000, 10); -+ 5000000, 10); - /* Assume a buggy HC and start HC initialization anyway */ - if (timeout) { - val = readl(op_reg_base + XHCI_STS_OFFSET); -diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h -index fc2ee6c272c4..1715705acc59 100644 ---- a/drivers/usb/host/xhci.h -+++ b/drivers/usb/host/xhci.h -@@ -1490,7 +1490,7 @@ struct xhci_bus_state { - - static inline unsigned int hcd_index(struct usb_hcd *hcd) - { -- if (hcd->speed == HCD_USB3) -+ if (hcd->speed >= HCD_USB3) - return 0; - else - return 1; -diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c -index 36e5b5c530bd..d95cd1a72b66 100644 ---- a/drivers/usb/renesas_usbhs/fifo.c -+++ b/drivers/usb/renesas_usbhs/fifo.c -@@ -285,11 +285,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, - struct usbhs_fifo *fifo) - { - struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); -+ int ret = 0; - -- if (!usbhs_pipe_is_dcp(pipe)) -- usbhsf_fifo_barrier(priv, fifo); -+ if (!usbhs_pipe_is_dcp(pipe)) { -+ /* -+ * This driver checks the pipe condition first to avoid -EBUSY -+ * from usbhsf_fifo_barrier() with about 10 msec delay in -+ * the interrupt handler if the pipe is RX direction and empty. -+ */ -+ if (usbhs_pipe_is_dir_in(pipe)) -+ ret = usbhs_pipe_is_accessible(pipe); -+ if (!ret) -+ ret = usbhsf_fifo_barrier(priv, fifo); -+ } - -- usbhs_write(priv, fifo->ctr, BCLR); -+ /* -+ * if non-DCP pipe, this driver should set BCLR when -+ * usbhsf_fifo_barrier() returns 0. -+ */ -+ if (!ret) -+ usbhs_write(priv, fifo->ctr, BCLR); - } - - static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, -diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h -index f58caa9e6a27..a155cd02bce2 100644 ---- a/drivers/usb/storage/uas-detect.h -+++ b/drivers/usb/storage/uas-detect.h -@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf) - intf->desc.bInterfaceProtocol == USB_PR_UAS); - } - --static int uas_find_uas_alt_setting(struct usb_interface *intf) -+static struct usb_host_interface *uas_find_uas_alt_setting( -+ struct usb_interface *intf) - { - int i; - -@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf) - struct usb_host_interface *alt = &intf->altsetting[i]; - - if (uas_is_interface(alt)) -- return alt->desc.bAlternateSetting; -+ return alt; - } - -- return -ENODEV; -+ return NULL; - } - - static int uas_find_endpoints(struct usb_host_interface *alt, -@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf, - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - unsigned long flags = id->driver_info; -- int r, alt; -- -+ struct usb_host_interface *alt; -+ int r; - - alt = uas_find_uas_alt_setting(intf); -- if (alt < 0) -+ if (!alt) - return 0; - -- r = uas_find_endpoints(&intf->altsetting[alt], eps); -+ r = uas_find_endpoints(alt, eps); - if (r < 0) - return 0; - -diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c -index e26e32169a36..f952635ebe5f 100644 ---- a/drivers/usb/storage/uas.c -+++ b/drivers/usb/storage/uas.c -@@ -849,14 +849,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids); - static int uas_switch_interface(struct usb_device *udev, - struct usb_interface *intf) - { -- int alt; -+ struct usb_host_interface *alt; - - alt = uas_find_uas_alt_setting(intf); -- if (alt < 0) -- return alt; -+ if (!alt) -+ return -ENODEV; - -- return usb_set_interface(udev, -- intf->altsetting[0].desc.bInterfaceNumber, alt); -+ return usb_set_interface(udev, alt->desc.bInterfaceNumber, -+ alt->desc.bAlternateSetting); - } - - static int uas_configure_endpoints(struct uas_dev_info *devinfo) -diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h -index 640a2e2ec04d..fb96755550ec 100644 ---- a/drivers/usb/storage/unusual_devs.h -+++ b/drivers/usb/storage/unusual_devs.h -@@ -1379,6 +1379,13 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_SANE_SENSE ), - -+/* Reported by Kris Lindgren */ -+UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999, -+ "Seagate", -+ "External", -+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, -+ US_FL_NO_WP_DETECT ), -+ - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, - "Maxtor", - "USB to SATA", -diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c -index e75bbe5a10cd..1212b4b3c5a9 100644 ---- a/drivers/uwb/hwa-rc.c -+++ b/drivers/uwb/hwa-rc.c -@@ -827,6 +827,8 @@ static int hwarc_probe(struct usb_interface *iface, - - if (iface->cur_altsetting->desc.bNumEndpoints < 1) - return -ENODEV; -+ if (!usb_endpoint_xfer_int(&iface->cur_altsetting->endpoint[0].desc)) -+ return -ENODEV; - - result = -ENOMEM; - uwb_rc = uwb_rc_alloc(); -diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c -index bdcb13cc1d54..5c9828370217 100644 ---- a/drivers/uwb/uwbd.c -+++ b/drivers/uwb/uwbd.c -@@ -303,18 +303,22 @@ static int uwbd(void *param) - /** Start the UWB daemon */ - void uwbd_start(struct uwb_rc *rc) - { -- rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); -- if (rc->uwbd.task == NULL) -+ struct task_struct *task = kthread_run(uwbd, rc, "uwbd"); -+ if (IS_ERR(task)) { -+ rc->uwbd.task = NULL; - printk(KERN_ERR "UWB: Cannot start management daemon; " - "UWB won't work\n"); -- else -+ } else { -+ rc->uwbd.task = task; - rc->uwbd.pid = rc->uwbd.task->pid; -+ } - } - - /* Stop the UWB daemon and free any unprocessed events */ - void uwbd_stop(struct uwb_rc *rc) - { -- kthread_stop(rc->uwbd.task); -+ if (rc->uwbd.task) -+ kthread_stop(rc->uwbd.task); - uwbd_flush(rc); - } - -diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c -index c3fe1e323951..ea2ef0eac0c4 100644 ---- a/fs/ext4/acl.c -+++ b/fs/ext4/acl.c -@@ -195,13 +195,6 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, - switch (type) { - case ACL_TYPE_ACCESS: - name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; -- if (acl) { -- error = posix_acl_update_mode(inode, &inode->i_mode, &acl); -- if (error) -- return error; -- inode->i_ctime = ext4_current_time(inode); -- ext4_mark_inode_dirty(handle, inode); -- } - break; - - case ACL_TYPE_DEFAULT: -@@ -234,6 +227,8 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) - { - handle_t *handle; - int error, retries = 0; -+ umode_t mode = inode->i_mode; -+ int update_mode = 0; - - retry: - handle = ext4_journal_start(inode, EXT4_HT_XATTR, -@@ -241,7 +236,20 @@ retry: - if (IS_ERR(handle)) - return PTR_ERR(handle); - -+ if ((type == ACL_TYPE_ACCESS) && acl) { -+ error = posix_acl_update_mode(inode, &mode, &acl); -+ if (error) -+ goto out_stop; -+ update_mode = 1; -+ } -+ - error = __ext4_set_acl(handle, inode, type, acl); -+ if (!error && update_mode) { -+ inode->i_mode = mode; -+ inode->i_ctime = ext4_current_time(inode); -+ ext4_mark_inode_dirty(handle, inode); -+ } -+out_stop: - ext4_journal_stop(handle); - if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) - goto retry; -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 1796d1bd9a1d..194a6baa4283 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -1946,15 +1946,29 @@ static int ext4_writepage(struct page *page, - static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page) - { - int len; -- loff_t size = i_size_read(mpd->inode); -+ loff_t size; - int err; - - BUG_ON(page->index != mpd->first_page); -- if (page->index == size >> PAGE_CACHE_SHIFT) -- len = size & ~PAGE_CACHE_MASK; -- else -- len = PAGE_CACHE_SIZE; - clear_page_dirty_for_io(page); -+ /* -+ * We have to be very careful here! Nothing protects writeback path -+ * against i_size changes and the page can be writeably mapped into -+ * page tables. So an application can be growing i_size and writing -+ * data through mmap while writeback runs. clear_page_dirty_for_io() -+ * write-protects our page in page tables and the page cannot get -+ * written to again until we release page lock. So only after -+ * clear_page_dirty_for_io() we are safe to sample i_size for -+ * ext4_bio_write_page() to zero-out tail of the written page. We rely -+ * on the barrier provided by TestClearPageDirty in -+ * clear_page_dirty_for_io() to make sure i_size is really sampled only -+ * after page tables are updated. -+ */ -+ size = i_size_read(mpd->inode); -+ if (page->index == size >> PAGE_SHIFT) -+ len = size & ~PAGE_MASK; -+ else -+ len = PAGE_SIZE; - err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false); - if (!err) - mpd->wbc->nr_to_write--; -diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c -index 1d007e853f5c..6445d84266fa 100644 ---- a/fs/ext4/namei.c -+++ b/fs/ext4/namei.c -@@ -3506,6 +3506,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, - int credits; - u8 old_file_type; - -+ if ((ext4_encrypted_inode(old_dir) && -+ !ext4_has_encryption_key(old_dir)) || -+ (ext4_encrypted_inode(new_dir) && -+ !ext4_has_encryption_key(new_dir))) -+ return -ENOKEY; -+ - retval = dquot_initialize(old.dir); - if (retval) - return retval; -@@ -3706,6 +3712,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, - u8 new_file_type; - int retval; - -+ if ((ext4_encrypted_inode(old_dir) && -+ !ext4_has_encryption_key(old_dir)) || -+ (ext4_encrypted_inode(new_dir) && -+ !ext4_has_encryption_key(new_dir))) -+ return -ENOKEY; -+ - if ((ext4_encrypted_inode(old_dir) || - ext4_encrypted_inode(new_dir)) && - (old_dir != new_dir) && -diff --git a/fs/xattr.c b/fs/xattr.c -index f0da9d24e9ca..76f01bf4b048 100644 ---- a/fs/xattr.c -+++ b/fs/xattr.c -@@ -163,7 +163,7 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value, - } - memcpy(value, buffer, len); - out: -- security_release_secctx(buffer, len); -+ kfree(buffer); - out_noalloc: - return len; - } -diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h -index 8397dc235e84..ad98acfbcba8 100644 ---- a/include/linux/cpuset.h -+++ b/include/linux/cpuset.h -@@ -43,7 +43,9 @@ static inline void cpuset_dec(void) - - extern int cpuset_init(void); - extern void cpuset_init_smp(void); -+extern void cpuset_force_rebuild(void); - extern void cpuset_update_active_cpus(bool cpu_online); -+extern void cpuset_wait_for_hotplug(void); - extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); - extern void cpuset_cpus_allowed_fallback(struct task_struct *p); - extern nodemask_t cpuset_mems_allowed(struct task_struct *p); -@@ -147,11 +149,15 @@ static inline bool cpusets_enabled(void) { return false; } - static inline int cpuset_init(void) { return 0; } - static inline void cpuset_init_smp(void) {} - -+static inline void cpuset_force_rebuild(void) { } -+ - static inline void cpuset_update_active_cpus(bool cpu_online) - { - partition_sched_domains(1, NULL, NULL); - } - -+static inline void cpuset_wait_for_hotplug(void) { } -+ - static inline void cpuset_cpus_allowed(struct task_struct *p, - struct cpumask *mask) - { -diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h -index e7fdec4db9da..6cc48ac55fd2 100644 ---- a/include/linux/iio/adc/ad_sigma_delta.h -+++ b/include/linux/iio/adc/ad_sigma_delta.h -@@ -111,6 +111,9 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, - int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, - unsigned int size, unsigned int *val); - -+int ad_sd_reset(struct ad_sigma_delta *sigma_delta, -+ unsigned int reset_length); -+ - int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, int *val); - int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta, -diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h -index 779a62aafafe..91ab75c1013c 100644 ---- a/include/uapi/linux/usb/ch9.h -+++ b/include/uapi/linux/usb/ch9.h -@@ -717,6 +717,7 @@ struct usb_interface_assoc_descriptor { - __u8 iFunction; - } __attribute__ ((packed)); - -+#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 - - /*-------------------------------------------------------------------------*/ - -diff --git a/kernel/cpuset.c b/kernel/cpuset.c -index 2924b6faa469..dd3ae6ee064d 100644 ---- a/kernel/cpuset.c -+++ b/kernel/cpuset.c -@@ -2281,6 +2281,13 @@ retry: - mutex_unlock(&cpuset_mutex); - } - -+static bool force_rebuild; -+ -+void cpuset_force_rebuild(void) -+{ -+ force_rebuild = true; -+} -+ - /** - * cpuset_hotplug_workfn - handle CPU/memory hotunplug for a cpuset - * -@@ -2355,8 +2362,10 @@ static void cpuset_hotplug_workfn(struct work_struct *work) - } - - /* rebuild sched domains if cpus_allowed has changed */ -- if (cpus_updated) -+ if (cpus_updated || force_rebuild) { -+ force_rebuild = false; - rebuild_sched_domains(); -+ } - } - - void cpuset_update_active_cpus(bool cpu_online) -@@ -2375,6 +2384,11 @@ void cpuset_update_active_cpus(bool cpu_online) - schedule_work(&cpuset_hotplug_work); - } - -+void cpuset_wait_for_hotplug(void) -+{ -+ flush_work(&cpuset_hotplug_work); -+} -+ - /* - * Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY]. - * Call this routine anytime after node_states[N_MEMORY] changes. -diff --git a/kernel/power/process.c b/kernel/power/process.c -index 564f786df470..ba2029a02259 100644 ---- a/kernel/power/process.c -+++ b/kernel/power/process.c -@@ -18,8 +18,9 @@ - #include - #include - #include -+#include - --/* -+/* - * Timeout for stopping processes - */ - unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC; -@@ -198,6 +199,8 @@ void thaw_processes(void) - __usermodehelper_set_disable_depth(UMH_FREEZING); - thaw_workqueues(); - -+ cpuset_wait_for_hotplug(); -+ - read_lock(&tasklist_lock); - for_each_process_thread(g, p) { - /* No other threads should have PF_SUSPEND_TASK set */ -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index dece705b7f8c..b5d372083624 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -7286,17 +7286,16 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, - * operation in the resume sequence, just build a single sched - * domain, ignoring cpusets. - */ -- num_cpus_frozen--; -- if (likely(num_cpus_frozen)) { -- partition_sched_domains(1, NULL, NULL); -+ partition_sched_domains(1, NULL, NULL); -+ if (--num_cpus_frozen) - break; -- } - - /* - * This is the last CPU online operation. So fall through and - * restore the original sched domains by considering the - * cpuset configurations. - */ -+ cpuset_force_rebuild(); - - case CPU_ONLINE: - cpuset_update_active_cpus(true); -diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index 38d73a6e2857..fc0051fd672d 100644 ---- a/kernel/trace/ftrace.c -+++ b/kernel/trace/ftrace.c -@@ -4315,9 +4315,6 @@ static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; - static char ftrace_graph_notrace_buf[FTRACE_FILTER_SIZE] __initdata; - static int ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer); - --static unsigned long save_global_trampoline; --static unsigned long save_global_flags; -- - static int __init set_graph_function(char *str) - { - strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE); -@@ -5907,17 +5904,6 @@ void unregister_ftrace_graph(void) - unregister_pm_notifier(&ftrace_suspend_notifier); - unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); - --#ifdef CONFIG_DYNAMIC_FTRACE -- /* -- * Function graph does not allocate the trampoline, but -- * other global_ops do. We need to reset the ALLOC_TRAMP flag -- * if one was used. -- */ -- global_ops.trampoline = save_global_trampoline; -- if (save_global_flags & FTRACE_OPS_FL_ALLOC_TRAMP) -- global_ops.flags |= FTRACE_OPS_FL_ALLOC_TRAMP; --#endif -- - out: - mutex_unlock(&ftrace_lock); - } -diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c -index 7c57c7fcf5a2..735a1a9386d6 100644 ---- a/security/smack/smack_lsm.c -+++ b/security/smack/smack_lsm.c -@@ -1459,7 +1459,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) - * @inode: the object - * @name: attribute name - * @buffer: where to put the result -- * @alloc: unused -+ * @alloc: duplicate memory - * - * Returns the size of the attribute or an error code - */ -@@ -1472,43 +1472,38 @@ static int smack_inode_getsecurity(const struct inode *inode, - struct super_block *sbp; - struct inode *ip = (struct inode *)inode; - struct smack_known *isp; -- int ilen; -- int rc = 0; - -- if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { -+ if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) - isp = smk_of_inode(inode); -- ilen = strlen(isp->smk_known); -- *buffer = isp->smk_known; -- return ilen; -- } -+ else { -+ /* -+ * The rest of the Smack xattrs are only on sockets. -+ */ -+ sbp = ip->i_sb; -+ if (sbp->s_magic != SOCKFS_MAGIC) -+ return -EOPNOTSUPP; - -- /* -- * The rest of the Smack xattrs are only on sockets. -- */ -- sbp = ip->i_sb; -- if (sbp->s_magic != SOCKFS_MAGIC) -- return -EOPNOTSUPP; -+ sock = SOCKET_I(ip); -+ if (sock == NULL || sock->sk == NULL) -+ return -EOPNOTSUPP; - -- sock = SOCKET_I(ip); -- if (sock == NULL || sock->sk == NULL) -- return -EOPNOTSUPP; -- -- ssp = sock->sk->sk_security; -+ ssp = sock->sk->sk_security; - -- if (strcmp(name, XATTR_SMACK_IPIN) == 0) -- isp = ssp->smk_in; -- else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) -- isp = ssp->smk_out; -- else -- return -EOPNOTSUPP; -+ if (strcmp(name, XATTR_SMACK_IPIN) == 0) -+ isp = ssp->smk_in; -+ else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) -+ isp = ssp->smk_out; -+ else -+ return -EOPNOTSUPP; -+ } - -- ilen = strlen(isp->smk_known); -- if (rc == 0) { -- *buffer = isp->smk_known; -- rc = ilen; -+ if (alloc) { -+ *buffer = kstrdup(isp->smk_known, GFP_KERNEL); -+ if (*buffer == NULL) -+ return -ENOMEM; - } - -- return rc; -+ return strlen(isp->smk_known); - } - - -diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c -index b554d7f9e3be..6163bf3e8177 100644 ---- a/sound/core/compress_offload.c -+++ b/sound/core/compress_offload.c -@@ -872,14 +872,13 @@ static const struct file_operations snd_compr_file_ops = { - static int snd_compress_dev_register(struct snd_device *device) - { - int ret = -EINVAL; -- char str[16]; - struct snd_compr *compr; - - if (snd_BUG_ON(!device || !device->device_data)) - return -EBADFD; - compr = device->device_data; - -- pr_debug("reg %s for device %s, direction %d\n", str, compr->name, -+ pr_debug("reg device %s, direction %d\n", compr->name, - compr->direction); - /* register compressed device */ - ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, -diff --git a/sound/usb/card.c b/sound/usb/card.c -index a1cbaa5f7fc9..83336bb6333e 100644 ---- a/sound/usb/card.c -+++ b/sound/usb/card.c -@@ -217,6 +217,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) - struct usb_interface_descriptor *altsd; - void *control_header; - int i, protocol; -+ int rest_bytes; - - /* find audiocontrol interface */ - host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; -@@ -231,6 +232,15 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) - return -EINVAL; - } - -+ rest_bytes = (void *)(host_iface->extra + host_iface->extralen) - -+ control_header; -+ -+ /* just to be sure -- this shouldn't hit at all */ -+ if (rest_bytes <= 0) { -+ dev_err(&dev->dev, "invalid control header\n"); -+ return -EINVAL; -+ } -+ - switch (protocol) { - default: - dev_warn(&dev->dev, -@@ -241,11 +251,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) - case UAC_VERSION_1: { - struct uac1_ac_header_descriptor *h1 = control_header; - -+ if (rest_bytes < sizeof(*h1)) { -+ dev_err(&dev->dev, "too short v1 buffer descriptor\n"); -+ return -EINVAL; -+ } -+ - if (!h1->bInCollection) { - dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); - return -EINVAL; - } - -+ if (rest_bytes < h1->bLength) { -+ dev_err(&dev->dev, "invalid buffer length (v1)\n"); -+ return -EINVAL; -+ } -+ - if (h1->bLength < sizeof(*h1) + h1->bInCollection) { - dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); - return -EINVAL; -diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c -index bf618e1500ac..e7b934f4d837 100644 ---- a/sound/usb/usx2y/usb_stream.c -+++ b/sound/usb/usx2y/usb_stream.c -@@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, - } - - pg = get_order(read_size); -- sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); -+ sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| -+ __GFP_NOWARN, pg); - if (!sk->s) { - snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); - goto out; -@@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, - pg = get_order(write_size); - - sk->write_page = -- (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); -+ (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| -+ __GFP_NOWARN, pg); - if (!sk->write_page) { - snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); - usb_stream_free(sk); diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.92-93.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.92-93.patch deleted file mode 100644 index 08ef2569a..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.92-93.patch +++ /dev/null @@ -1,933 +0,0 @@ -diff --git a/Makefile b/Makefile -index fab2d640a27e..77a17fb24b6d 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 92 -+SUBLEVEL = 93 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c -index 6da2e4a6ba39..dd058aa8a3b5 100644 ---- a/arch/mips/math-emu/cp1emu.c -+++ b/arch/mips/math-emu/cp1emu.c -@@ -2360,7 +2360,6 @@ dcopuop: - break; - default: - /* Reserved R6 ops */ -- pr_err("Reserved MIPS R6 CMP.condn.S operation\n"); - return SIGILL; - } - } -@@ -2434,7 +2433,6 @@ dcopuop: - break; - default: - /* Reserved R6 ops */ -- pr_err("Reserved MIPS R6 CMP.condn.D operation\n"); - return SIGILL; - } - } -diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h -index e7636bac7372..6c98821fef5e 100644 ---- a/arch/x86/include/asm/alternative-asm.h -+++ b/arch/x86/include/asm/alternative-asm.h -@@ -62,8 +62,10 @@ - #define new_len2 145f-144f - - /* -- * max without conditionals. Idea adapted from: -+ * gas compatible max based on the idea from: - * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax -+ * -+ * The additional "-" is needed because gas uses a "true" value of -1. - */ - #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b))))) - -diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h -index 7bfc85bbb8ff..09936e9c8154 100644 ---- a/arch/x86/include/asm/alternative.h -+++ b/arch/x86/include/asm/alternative.h -@@ -102,12 +102,12 @@ static inline int alternatives_text_reserved(void *start, void *end) - alt_end_marker ":\n" - - /* -- * max without conditionals. Idea adapted from: -+ * gas compatible max based on the idea from: - * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax - * -- * The additional "-" is needed because gas works with s32s. -+ * The additional "-" is needed because gas uses a "true" value of -1. - */ --#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") - (" b ")))))" -+#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))" - - /* - * Pad the second replacement alternative with additional NOPs if it is -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index a018dff00808..9114588e3e61 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -10369,7 +10369,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, - * (KVM doesn't change it)- no reason to call set_cr4_guest_host_mask(); - */ - vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK); -- kvm_set_cr4(vcpu, vmcs12->host_cr4); -+ vmx_set_cr4(vcpu, vmcs12->host_cr4); - - nested_ept_uninit_mmu_context(vcpu); - -diff --git a/block/bio.c b/block/bio.c -index 14263fab94d3..68bbc835bacc 100644 ---- a/block/bio.c -+++ b/block/bio.c -@@ -1320,6 +1320,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, - offset = uaddr & ~PAGE_MASK; - for (j = cur_page; j < page_limit; j++) { - unsigned int bytes = PAGE_SIZE - offset; -+ unsigned short prev_bi_vcnt = bio->bi_vcnt; - - if (len <= 0) - break; -@@ -1334,6 +1335,13 @@ struct bio *bio_map_user_iov(struct request_queue *q, - bytes) - break; - -+ /* -+ * check if vector was merged with previous -+ * drop page reference if needed -+ */ -+ if (bio->bi_vcnt == prev_bi_vcnt) -+ put_page(pages[j]); -+ - len -= bytes; - offset = 0; - } -diff --git a/crypto/shash.c b/crypto/shash.c -index 359754591653..b2cd109d9171 100644 ---- a/crypto/shash.c -+++ b/crypto/shash.c -@@ -274,12 +274,14 @@ static int shash_async_finup(struct ahash_request *req) - - int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc) - { -- struct scatterlist *sg = req->src; -- unsigned int offset = sg->offset; - unsigned int nbytes = req->nbytes; -+ struct scatterlist *sg; -+ unsigned int offset; - int err; - -- if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { -+ if (nbytes && -+ (sg = req->src, offset = sg->offset, -+ nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) { - void *data; - - data = kmap_atomic(sg_page(sg)); -diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c -index 16fe773fb846..85674a8d0436 100644 ---- a/drivers/dma/edma.c -+++ b/drivers/dma/edma.c -@@ -1126,11 +1126,24 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( - struct edma_desc *edesc; - struct device *dev = chan->device->dev; - struct edma_chan *echan = to_edma_chan(chan); -- unsigned int width, pset_len; -+ unsigned int width, pset_len, array_size; - - if (unlikely(!echan || !len)) - return NULL; - -+ /* Align the array size (acnt block) with the transfer properties */ -+ switch (__ffs((src | dest | len))) { -+ case 0: -+ array_size = SZ_32K - 1; -+ break; -+ case 1: -+ array_size = SZ_32K - 2; -+ break; -+ default: -+ array_size = SZ_32K - 4; -+ break; -+ } -+ - if (len < SZ_64K) { - /* - * Transfer size less than 64K can be handled with one paRAM -@@ -1152,7 +1165,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( - * When the full_length is multibple of 32767 one slot can be - * used to complete the transfer. - */ -- width = SZ_32K - 1; -+ width = array_size; - pset_len = rounddown(len, width); - /* One slot is enough for lengths multiple of (SZ_32K -1) */ - if (unlikely(pset_len == len)) -@@ -1202,7 +1215,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( - } - dest += pset_len; - src += pset_len; -- pset_len = width = len % (SZ_32K - 1); -+ pset_len = width = len % array_size; - - ret = edma_config_pset(chan, &edesc->pset[1], src, dest, 1, - width, pset_len, DMA_MEM_TO_MEM); -diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index 0df32fe0e345..b0eeb5090c91 100644 ---- a/drivers/hid/usbhid/hid-core.c -+++ b/drivers/hid/usbhid/hid-core.c -@@ -971,6 +971,8 @@ static int usbhid_parse(struct hid_device *hid) - unsigned int rsize = 0; - char *rdesc; - int ret, n; -+ int num_descriptors; -+ size_t offset = offsetof(struct hid_descriptor, desc); - - quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); -@@ -993,10 +995,18 @@ static int usbhid_parse(struct hid_device *hid) - return -ENODEV; - } - -+ if (hdesc->bLength < sizeof(struct hid_descriptor)) { -+ dbg_hid("hid descriptor is too short\n"); -+ return -EINVAL; -+ } -+ - hid->version = le16_to_cpu(hdesc->bcdHID); - hid->country = hdesc->bCountryCode; - -- for (n = 0; n < hdesc->bNumDescriptors; n++) -+ num_descriptors = min_t(int, hdesc->bNumDescriptors, -+ (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); -+ -+ for (n = 0; n < num_descriptors; n++) - if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) - rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); - -diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c -index a0ef57483ebb..52c36394dba5 100644 ---- a/drivers/iommu/amd_iommu.c -+++ b/drivers/iommu/amd_iommu.c -@@ -3096,6 +3096,7 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, - mutex_unlock(&domain->api_lock); - - domain_flush_tlb_pde(domain); -+ domain_flush_complete(domain); - - return unmap_size; - } -diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -index f18491cf793c..5fecae0ba52e 100644 ---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -@@ -2903,6 +2903,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - s32 status; - struct brcmf_escan_result_le *escan_result_le; -+ u32 escan_buflen; - struct brcmf_bss_info_le *bss_info_le; - struct brcmf_bss_info_le *bss = NULL; - u32 bi_length; -@@ -2919,11 +2920,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, - - if (status == BRCMF_E_STATUS_PARTIAL) { - brcmf_dbg(SCAN, "ESCAN Partial result\n"); -+ if (e->datalen < sizeof(*escan_result_le)) { -+ brcmf_err("invalid event data length\n"); -+ goto exit; -+ } - escan_result_le = (struct brcmf_escan_result_le *) data; - if (!escan_result_le) { - brcmf_err("Invalid escan result (NULL pointer)\n"); - goto exit; - } -+ escan_buflen = le32_to_cpu(escan_result_le->buflen); -+ if (escan_buflen > WL_ESCAN_BUF_SIZE || -+ escan_buflen > e->datalen || -+ escan_buflen < sizeof(*escan_result_le)) { -+ brcmf_err("Invalid escan buffer length: %d\n", -+ escan_buflen); -+ goto exit; -+ } - if (le16_to_cpu(escan_result_le->bss_count) != 1) { - brcmf_err("Invalid bss_count %d: ignoring\n", - escan_result_le->bss_count); -@@ -2940,9 +2953,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, - } - - bi_length = le32_to_cpu(bss_info_le->length); -- if (bi_length != (le32_to_cpu(escan_result_le->buflen) - -- WL_ESCAN_RESULTS_FIXED_SIZE)) { -- brcmf_err("Invalid bss_info length %d: ignoring\n", -+ if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { -+ brcmf_err("Ignoring invalid bss_info length: %d\n", - bi_length); - goto exit; - } -diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c -index 1a8ea775de08..984cd2f05c4a 100644 ---- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c -+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c -@@ -1906,6 +1906,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, - struct iwl_mvm_mc_iter_data *data = _data; - struct iwl_mvm *mvm = data->mvm; - struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; -+ struct iwl_host_cmd hcmd = { -+ .id = MCAST_FILTER_CMD, -+ .flags = CMD_ASYNC, -+ .dataflags[0] = IWL_HCMD_DFL_NOCOPY, -+ }; - int ret, len; - - /* if we don't have free ports, mcast frames will be dropped */ -@@ -1920,7 +1925,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, - memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); - len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); - -- ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); -+ hcmd.len[0] = len; -+ hcmd.data[0] = cmd; -+ -+ ret = iwl_mvm_send_cmd(mvm, &hcmd); - if (ret) - IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); - } -diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c -index e2641d4dfdd6..d186d0282a38 100644 ---- a/drivers/usb/gadget/composite.c -+++ b/drivers/usb/gadget/composite.c -@@ -1905,6 +1905,8 @@ static DEVICE_ATTR_RO(suspended); - static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) - { - struct usb_composite_dev *cdev = get_gadget_data(gadget); -+ struct usb_gadget_strings *gstr = cdev->driver->strings[0]; -+ struct usb_string *dev_str = gstr->strings; - - /* composite_disconnect() must already have been called - * by the underlying peripheral controller driver! -@@ -1924,6 +1926,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) - - composite_dev_cleanup(cdev); - -+ if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer) -+ dev_str[USB_GADGET_MANUFACTURER_IDX].s = ""; -+ - kfree(cdev->def_manufacturer); - kfree(cdev); - set_gadget_data(gadget, NULL); -diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c -index db645c38055d..8080a11947b7 100644 ---- a/drivers/usb/gadget/udc/dummy_hcd.c -+++ b/drivers/usb/gadget/udc/dummy_hcd.c -@@ -420,6 +420,7 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd) - static void set_link_state(struct dummy_hcd *dum_hcd) - { - struct dummy *dum = dum_hcd->dum; -+ unsigned int power_bit; - - dum_hcd->active = 0; - if (dum->pullup) -@@ -430,17 +431,19 @@ static void set_link_state(struct dummy_hcd *dum_hcd) - return; - - set_link_state_by_speed(dum_hcd); -+ power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ? -+ USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER); - - if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 || - dum_hcd->active) - dum_hcd->resuming = 0; - - /* Currently !connected or in reset */ -- if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 || -+ if ((dum_hcd->port_status & power_bit) == 0 || - (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) { -- unsigned disconnect = USB_PORT_STAT_CONNECTION & -+ unsigned int disconnect = power_bit & - dum_hcd->old_status & (~dum_hcd->port_status); -- unsigned reset = USB_PORT_STAT_RESET & -+ unsigned int reset = USB_PORT_STAT_RESET & - (~dum_hcd->old_status) & dum_hcd->port_status; - - /* Report reset and disconnect events to the driver */ -diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c -index d95cd1a72b66..8bb9367ada45 100644 ---- a/drivers/usb/renesas_usbhs/fifo.c -+++ b/drivers/usb/renesas_usbhs/fifo.c -@@ -858,9 +858,9 @@ static void xfer_work(struct work_struct *work) - fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); - - usbhs_pipe_running(pipe, 1); -- usbhsf_dma_start(pipe, fifo); - usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); - dma_async_issue_pending(chan); -+ usbhsf_dma_start(pipe, fifo); - usbhs_pipe_enable(pipe); - - xfer_work_end: -diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c -index 3806e7014199..2938153fe7b1 100644 ---- a/drivers/usb/serial/console.c -+++ b/drivers/usb/serial/console.c -@@ -189,6 +189,7 @@ static int usb_console_setup(struct console *co, char *options) - tty_kref_put(tty); - reset_open_count: - port->port.count = 0; -+ info->port = NULL; - usb_autopm_put_interface(serial->interface); - error_get_interface: - usb_serial_put(serial); -diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c -index 41a6513646de..1f5ecf905b7d 100644 ---- a/drivers/usb/serial/cp210x.c -+++ b/drivers/usb/serial/cp210x.c -@@ -170,6 +170,7 @@ static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ -+ { USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */ - { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ - { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ - { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ -diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c -index e0385d6c0abb..30344efc123f 100644 ---- a/drivers/usb/serial/ftdi_sio.c -+++ b/drivers/usb/serial/ftdi_sio.c -@@ -1015,6 +1015,8 @@ static const struct usb_device_id id_table_combined[] = { - { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) }, - { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, -+ { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) }, -+ { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) }, - { } /* Terminating entry */ - }; - -diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h -index 4fcf1cecb6d7..f9d15bd62785 100644 ---- a/drivers/usb/serial/ftdi_sio_ids.h -+++ b/drivers/usb/serial/ftdi_sio_ids.h -@@ -609,6 +609,13 @@ - #define ADI_GNICE_PID 0xF000 - #define ADI_GNICEPLUS_PID 0xF001 - -+/* -+ * Cypress WICED USB UART -+ */ -+#define CYPRESS_VID 0x04B4 -+#define CYPRESS_WICED_BT_USB_PID 0x009B -+#define CYPRESS_WICED_WL_USB_PID 0xF900 -+ - /* - * Microchip Technology, Inc. - * -diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c -index 2a9944326210..db3d34c2c82e 100644 ---- a/drivers/usb/serial/option.c -+++ b/drivers/usb/serial/option.c -@@ -522,6 +522,7 @@ static void option_instat_callback(struct urb *urb); - - /* TP-LINK Incorporated products */ - #define TPLINK_VENDOR_ID 0x2357 -+#define TPLINK_PRODUCT_LTE 0x000D - #define TPLINK_PRODUCT_MA180 0x0201 - - /* Changhong products */ -@@ -2011,6 +2012,7 @@ static const struct usb_device_id option_ids[] = { - { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, - { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) }, - { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, TPLINK_PRODUCT_LTE, 0xff, 0x00, 0x00) }, /* TP-Link LTE Module */ - { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), - .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */ -diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c -index 652b4334b26d..e1c1e329c877 100644 ---- a/drivers/usb/serial/qcserial.c -+++ b/drivers/usb/serial/qcserial.c -@@ -174,6 +174,10 @@ static const struct usb_device_id id_table[] = { - {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ - {DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */ - {DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */ -+ {DEVICE_SWI(0x413c, 0x81cf)}, /* Dell Wireless 5819 */ -+ {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ -+ {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ -+ {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ - - /* Huawei devices */ - {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ -diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h -index e2f6a79e9b01..8225de3c9743 100644 ---- a/fs/cifs/cifsglob.h -+++ b/fs/cifs/cifsglob.h -@@ -351,6 +351,8 @@ struct smb_version_operations { - unsigned int (*calc_smb_size)(void *); - /* check for STATUS_PENDING and process it in a positive case */ - bool (*is_status_pending)(char *, struct TCP_Server_Info *, int); -+ /* check for STATUS_NETWORK_SESSION_EXPIRED */ -+ bool (*is_session_expired)(char *); - /* send oplock break response */ - int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *, - struct cifsInodeInfo *); -diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c -index b60150e5b5ce..0c92af11f4f4 100644 ---- a/fs/cifs/cifssmb.c -+++ b/fs/cifs/cifssmb.c -@@ -1460,6 +1460,13 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) - return length; - server->total_read += length; - -+ if (server->ops->is_session_expired && -+ server->ops->is_session_expired(buf)) { -+ cifs_reconnect(server); -+ wake_up(&server->response_q); -+ return -1; -+ } -+ - if (server->ops->is_status_pending && - server->ops->is_status_pending(buf, server, 0)) { - discard_remaining_data(server); -diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c -index b377aa8f266f..0a2bf9462637 100644 ---- a/fs/cifs/connect.c -+++ b/fs/cifs/connect.c -@@ -850,6 +850,13 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) - cifs_dump_mem("Bad SMB: ", buf, - min_t(unsigned int, server->total_read, 48)); - -+ if (server->ops->is_session_expired && -+ server->ops->is_session_expired(buf)) { -+ cifs_reconnect(server); -+ wake_up(&server->response_q); -+ return -1; -+ } -+ - if (server->ops->is_status_pending && - server->ops->is_status_pending(buf, server, length)) - return -1; -diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c -index 1d125d3d0d89..e6b1795fbf2a 100644 ---- a/fs/cifs/smb2ops.c -+++ b/fs/cifs/smb2ops.c -@@ -963,6 +963,18 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) - return true; - } - -+static bool -+smb2_is_session_expired(char *buf) -+{ -+ struct smb2_hdr *hdr = (struct smb2_hdr *)buf; -+ -+ if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED) -+ return false; -+ -+ cifs_dbg(FYI, "Session expired\n"); -+ return true; -+} -+ - static int - smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid, - struct cifsInodeInfo *cinode) -@@ -1552,6 +1564,7 @@ struct smb_version_operations smb20_operations = { - .close_dir = smb2_close_dir, - .calc_smb_size = smb2_calc_size, - .is_status_pending = smb2_is_status_pending, -+ .is_session_expired = smb2_is_session_expired, - .oplock_response = smb2_oplock_response, - .queryfs = smb2_queryfs, - .mand_lock = smb2_mand_lock, -@@ -1633,6 +1646,7 @@ struct smb_version_operations smb21_operations = { - .close_dir = smb2_close_dir, - .calc_smb_size = smb2_calc_size, - .is_status_pending = smb2_is_status_pending, -+ .is_session_expired = smb2_is_session_expired, - .oplock_response = smb2_oplock_response, - .queryfs = smb2_queryfs, - .mand_lock = smb2_mand_lock, -@@ -1715,6 +1729,7 @@ struct smb_version_operations smb30_operations = { - .close_dir = smb2_close_dir, - .calc_smb_size = smb2_calc_size, - .is_status_pending = smb2_is_status_pending, -+ .is_session_expired = smb2_is_session_expired, - .oplock_response = smb2_oplock_response, - .queryfs = smb2_queryfs, - .mand_lock = smb2_mand_lock, -@@ -1803,6 +1818,7 @@ struct smb_version_operations smb311_operations = { - .close_dir = smb2_close_dir, - .calc_smb_size = smb2_calc_size, - .is_status_pending = smb2_is_status_pending, -+ .is_session_expired = smb2_is_session_expired, - .oplock_response = smb2_oplock_response, - .queryfs = smb2_queryfs, - .mand_lock = smb2_mand_lock, -diff --git a/fs/direct-io.c b/fs/direct-io.c -index c772fdf36cd9..44f49d86d714 100644 ---- a/fs/direct-io.c -+++ b/fs/direct-io.c -@@ -823,7 +823,8 @@ out: - */ - if (sdio->boundary) { - ret = dio_send_cur_page(dio, sdio, map_bh); -- dio_bio_submit(dio, sdio); -+ if (sdio->bio) -+ dio_bio_submit(dio, sdio); - page_cache_release(sdio->cur_page); - sdio->cur_page = NULL; - } -diff --git a/fs/ext4/file.c b/fs/ext4/file.c -index 45ef9975caec..a8b1749d79a8 100644 ---- a/fs/ext4/file.c -+++ b/fs/ext4/file.c -@@ -559,7 +559,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) - mutex_lock(&inode->i_mutex); - - isize = i_size_read(inode); -- if (offset >= isize) { -+ if (offset < 0 || offset >= isize) { - mutex_unlock(&inode->i_mutex); - return -ENXIO; - } -@@ -632,7 +632,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) - mutex_lock(&inode->i_mutex); - - isize = i_size_read(inode); -- if (offset >= isize) { -+ if (offset < 0 || offset >= isize) { - mutex_unlock(&inode->i_mutex); - return -ENXIO; - } -diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h -index a03acd0d398a..695257ae64ac 100644 ---- a/include/sound/seq_virmidi.h -+++ b/include/sound/seq_virmidi.h -@@ -60,6 +60,7 @@ struct snd_virmidi_dev { - int port; /* created/attached port */ - unsigned int flags; /* SNDRV_VIRMIDI_* */ - rwlock_t filelist_lock; -+ struct rw_semaphore filelist_sem; - struct list_head filelist; - }; - -diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c -index f07343b54fe5..8a62cbfe1f2f 100644 ---- a/kernel/rcu/tree.c -+++ b/kernel/rcu/tree.c -@@ -759,6 +759,12 @@ void rcu_irq_exit(void) - - local_irq_save(flags); - rdtp = this_cpu_ptr(&rcu_dynticks); -+ -+ /* Page faults can happen in NMI handlers, so check... */ -+ if (READ_ONCE(rdtp->dynticks_nmi_nesting)) -+ return; -+ -+ RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_exit() invoked with irqs enabled!!!"); - oldval = rdtp->dynticks_nesting; - rdtp->dynticks_nesting--; - WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && -@@ -887,6 +893,12 @@ void rcu_irq_enter(void) - - local_irq_save(flags); - rdtp = this_cpu_ptr(&rcu_dynticks); -+ -+ /* Page faults can happen in NMI handlers, so check... */ -+ if (READ_ONCE(rdtp->dynticks_nmi_nesting)) -+ return; -+ -+ RCU_LOCKDEP_WARN(!irqs_disabled(), "rcu_irq_enter() invoked with irqs enabled!!!"); - oldval = rdtp->dynticks_nesting; - rdtp->dynticks_nesting++; - WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 8ece212aa3d2..7950506395a8 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -485,6 +485,14 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = { - [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 }, - }; - -+/* policy for packet pattern attributes */ -+static const struct nla_policy -+nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = { -+ [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, }, -+ [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, }, -+ [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 }, -+}; -+ - static int nl80211_prepare_wdev_dump(struct sk_buff *skb, - struct netlink_callback *cb, - struct cfg80211_registered_device **rdev, -@@ -9410,7 +9418,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) - u8 *mask_pat; - - nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), -- nla_len(pat), NULL); -+ nla_len(pat), nl80211_packet_pattern_policy); - err = -EINVAL; - if (!pat_tb[NL80211_PKTPAT_MASK] || - !pat_tb[NL80211_PKTPAT_PATTERN]) -@@ -9660,7 +9668,7 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, - u8 *mask_pat; - - nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), -- nla_len(pat), NULL); -+ nla_len(pat), nl80211_packet_pattern_policy); - if (!pat_tb[NL80211_PKTPAT_MASK] || - !pat_tb[NL80211_PKTPAT_PATTERN]) - return -EINVAL; -diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c -index e326c1d80416..e847b9923c19 100644 ---- a/sound/core/seq/seq_clientmgr.c -+++ b/sound/core/seq/seq_clientmgr.c -@@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - struct snd_seq_client_port *port; - struct snd_seq_port_info info; - struct snd_seq_port_callback *callback; -+ int port_idx; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; -@@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - return -ENOMEM; - - if (client->type == USER_CLIENT && info.kernel) { -- snd_seq_delete_port(client, port->addr.port); -+ port_idx = port->addr.port; -+ snd_seq_port_unlock(port); -+ snd_seq_delete_port(client, port_idx); - return -EINVAL; - } - if (client->type == KERNEL_CLIENT) { -@@ -1294,6 +1297,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - - snd_seq_set_port_info(port, &info); - snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); -+ snd_seq_port_unlock(port); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; -diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c -index fe686ee41c6d..f04714d70bf7 100644 ---- a/sound/core/seq/seq_ports.c -+++ b/sound/core/seq/seq_ports.c -@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) - } - - --/* create a port, port number is returned (-1 on failure) */ -+/* create a port, port number is returned (-1 on failure); -+ * the caller needs to unref the port via snd_seq_port_unlock() appropriately -+ */ - struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, - int port) - { -@@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, - snd_use_lock_init(&new_port->use_lock); - port_subs_info_init(&new_port->c_src); - port_subs_info_init(&new_port->c_dest); -+ snd_use_lock_use(&new_port->use_lock); - - num = port >= 0 ? port : 0; - mutex_lock(&client->ports_mutex); -@@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, - list_add_tail(&new_port->list, &p->list); - client->num_ports++; - new_port->addr.port = num; /* store the port number in the port */ -+ sprintf(new_port->name, "port-%d", num); - write_unlock_irqrestore(&client->ports_lock, flags); - mutex_unlock(&client->ports_mutex); -- sprintf(new_port->name, "port-%d", num); - - return new_port; - } -diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c -index 81134e067184..3b126af4a026 100644 ---- a/sound/core/seq/seq_virmidi.c -+++ b/sound/core/seq/seq_virmidi.c -@@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi, - * decode input event and put to read buffer of each opened file - */ - static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, -- struct snd_seq_event *ev) -+ struct snd_seq_event *ev, -+ bool atomic) - { - struct snd_virmidi *vmidi; - unsigned char msg[4]; - int len; - -- read_lock(&rdev->filelist_lock); -+ if (atomic) -+ read_lock(&rdev->filelist_lock); -+ else -+ down_read(&rdev->filelist_sem); - list_for_each_entry(vmidi, &rdev->filelist, list) { - if (!vmidi->trigger) - continue; -@@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, - snd_rawmidi_receive(vmidi->substream, msg, len); - } - } -- read_unlock(&rdev->filelist_lock); -+ if (atomic) -+ read_unlock(&rdev->filelist_lock); -+ else -+ up_read(&rdev->filelist_sem); - - return 0; - } -@@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) - struct snd_virmidi_dev *rdev; - - rdev = rmidi->private_data; -- return snd_virmidi_dev_receive_event(rdev, ev); -+ return snd_virmidi_dev_receive_event(rdev, ev, true); - } - #endif /* 0 */ - -@@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct, - rdev = private_data; - if (!(rdev->flags & SNDRV_VIRMIDI_USE)) - return 0; /* ignored */ -- return snd_virmidi_dev_receive_event(rdev, ev); -+ return snd_virmidi_dev_receive_event(rdev, ev, atomic); - } - - /* -@@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) - struct snd_virmidi_dev *rdev = substream->rmidi->private_data; - struct snd_rawmidi_runtime *runtime = substream->runtime; - struct snd_virmidi *vmidi; -- unsigned long flags; - - vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); - if (vmidi == NULL) -@@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) - vmidi->client = rdev->client; - vmidi->port = rdev->port; - runtime->private_data = vmidi; -- write_lock_irqsave(&rdev->filelist_lock, flags); -+ down_write(&rdev->filelist_sem); -+ write_lock_irq(&rdev->filelist_lock); - list_add_tail(&vmidi->list, &rdev->filelist); -- write_unlock_irqrestore(&rdev->filelist_lock, flags); -+ write_unlock_irq(&rdev->filelist_lock); -+ up_write(&rdev->filelist_sem); - vmidi->rdev = rdev; - return 0; - } -@@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) - struct snd_virmidi_dev *rdev = substream->rmidi->private_data; - struct snd_virmidi *vmidi = substream->runtime->private_data; - -+ down_write(&rdev->filelist_sem); - write_lock_irq(&rdev->filelist_lock); - list_del(&vmidi->list); - write_unlock_irq(&rdev->filelist_lock); -+ up_write(&rdev->filelist_sem); - snd_midi_event_free(vmidi->parser); - substream->runtime->private_data = NULL; - kfree(vmidi); -@@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi - rdev->rmidi = rmidi; - rdev->device = device; - rdev->client = -1; -+ init_rwsem(&rdev->filelist_sem); - rwlock_init(&rdev->filelist_lock); - INIT_LIST_HEAD(&rdev->filelist); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; -diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c -index b871ba407e4e..4458190149d1 100644 ---- a/sound/usb/caiaq/device.c -+++ b/sound/usb/caiaq/device.c -@@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev) - - err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); - if (err) -- return err; -+ goto err_kill_urb; - -- if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) -- return -ENODEV; -+ if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) { -+ err = -ENODEV; -+ goto err_kill_urb; -+ } - - usb_string(usb_dev, usb_dev->descriptor.iManufacturer, - cdev->vendor_name, CAIAQ_USB_STR_LEN); -@@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev) - - setup_card(cdev); - return 0; -+ -+ err_kill_urb: -+ usb_kill_urb(&cdev->ep1_in_urb); -+ return err; - } - - static int snd_probe(struct usb_interface *intf, -diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c -index 183311cb849e..be78078a10ba 100644 ---- a/sound/usb/line6/driver.c -+++ b/sound/usb/line6/driver.c -@@ -586,9 +586,10 @@ int line6_probe(struct usb_interface *interface, - return 0; - - error: -- if (line6->disconnect) -- line6->disconnect(line6); -- snd_card_free(card); -+ /* we can call disconnect callback here because no close-sync is -+ * needed yet at this point -+ */ -+ line6_disconnect(interface); - return ret; - } - EXPORT_SYMBOL_GPL(line6_probe); -diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c -index 696de5ac69be..a23efc8671d6 100644 ---- a/sound/usb/mixer.c -+++ b/sound/usb/mixer.c -@@ -2161,6 +2161,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) - - static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) - { -+ /* kill pending URBs */ -+ snd_usb_mixer_disconnect(mixer); -+ - kfree(mixer->id_elems); - if (mixer->urb) { - kfree(mixer->urb->transfer_buffer); -@@ -2504,8 +2507,13 @@ _error: - - void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) - { -- usb_kill_urb(mixer->urb); -- usb_kill_urb(mixer->rc_urb); -+ if (mixer->disconnected) -+ return; -+ if (mixer->urb) -+ usb_kill_urb(mixer->urb); -+ if (mixer->rc_urb) -+ usb_kill_urb(mixer->rc_urb); -+ mixer->disconnected = true; - } - - #ifdef CONFIG_PM -diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h -index 2b4b067646ab..545d99b09706 100644 ---- a/sound/usb/mixer.h -+++ b/sound/usb/mixer.h -@@ -22,6 +22,8 @@ struct usb_mixer_interface { - struct urb *rc_urb; - struct usb_ctrlrequest *rc_setup_packet; - u8 rc_buffer[6]; -+ -+ bool disconnected; - }; - - #define MAX_CHANNELS 16 /* max logical channels */ diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.93-94.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.93-94.patch deleted file mode 100644 index 4a0013b84..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.93-94.patch +++ /dev/null @@ -1,1389 +0,0 @@ -diff --git a/Makefile b/Makefile -index 77a17fb24b6d..ff9d6bbf2210 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 93 -+SUBLEVEL = 94 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h -index 77edb22f855d..5433ccc9d706 100644 ---- a/arch/mips/include/asm/irq.h -+++ b/arch/mips/include/asm/irq.h -@@ -18,7 +18,7 @@ - #include - - #define IRQ_STACK_SIZE THREAD_SIZE --#define IRQ_STACK_START (IRQ_STACK_SIZE - sizeof(unsigned long)) -+#define IRQ_STACK_START (IRQ_STACK_SIZE - 16) - - extern void *irq_stack[NR_CPUS]; - -diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h -index be0cc1beed41..3fae200dd251 100644 ---- a/arch/sparc/include/asm/setup.h -+++ b/arch/sparc/include/asm/setup.h -@@ -59,8 +59,11 @@ extern atomic_t dcpage_flushes; - extern atomic_t dcpage_flushes_xcall; - - extern int sysctl_tsb_ratio; --#endif - -+#ifdef CONFIG_SERIAL_SUNHV -+void sunhv_migrate_hvcons_irq(int cpu); -+#endif -+#endif - void sun_do_break(void); - extern int stop_a_enabled; - extern int scons_pwroff; -diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c -index 4511caa3b7e9..46866b2097e8 100644 ---- a/arch/sparc/kernel/smp_64.c -+++ b/arch/sparc/kernel/smp_64.c -@@ -1443,8 +1443,12 @@ void smp_send_stop(void) - int cpu; - - if (tlb_type == hypervisor) { -+ int this_cpu = smp_processor_id(); -+#ifdef CONFIG_SERIAL_SUNHV -+ sunhv_migrate_hvcons_irq(this_cpu); -+#endif - for_each_online_cpu(cpu) { -- if (cpu == smp_processor_id()) -+ if (cpu == this_cpu) - continue; - #ifdef CONFIG_SUN_LDOMS - if (ldom_domaining_enabled) { -diff --git a/block/bsg-lib.c b/block/bsg-lib.c -index 341b8d858e67..650f427d915b 100644 ---- a/block/bsg-lib.c -+++ b/block/bsg-lib.c -@@ -147,6 +147,7 @@ static int bsg_create_job(struct device *dev, struct request *req) - failjob_rls_rqst_payload: - kfree(job->request_payload.sg_list); - failjob_rls_job: -+ kfree(job); - return -ENOMEM; - } - -diff --git a/crypto/Kconfig b/crypto/Kconfig -index 7240821137fd..617bf4a7da56 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -343,6 +343,7 @@ config CRYPTO_XTS - select CRYPTO_BLKCIPHER - select CRYPTO_MANAGER - select CRYPTO_GF128MUL -+ select CRYPTO_ECB - help - XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain, - key size 256, 384 or 512 bits. This implementation currently -diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index b1f8a73e5a94..eed1e073d96d 100644 ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -241,7 +241,7 @@ config ARM_PXA2xx_CPUFREQ - - config ACPI_CPPC_CPUFREQ - tristate "CPUFreq driver based on the ACPI CPPC spec" -- depends on ACPI -+ depends on ACPI_PROCESSOR - select ACPI_CPPC_LIB - default n - help -diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c -index 58bf94b69186..273e05a3c933 100644 ---- a/drivers/gpu/drm/drm_dp_mst_topology.c -+++ b/drivers/gpu/drm/drm_dp_mst_topology.c -@@ -1802,6 +1802,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) - return -EINVAL; - } - req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; -+ req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi; - } else { - port = NULL; - req_payload.num_slots = 0; -@@ -1817,6 +1818,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) - if (req_payload.num_slots) { - drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload); - mgr->payloads[i].num_slots = req_payload.num_slots; -+ mgr->payloads[i].vcpi = req_payload.vcpi; - } else if (mgr->payloads[i].num_slots) { - mgr->payloads[i].num_slots = 0; - drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]); -diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c -index 10835d1f559b..dee0fc421054 100644 ---- a/drivers/i2c/busses/i2c-at91.c -+++ b/drivers/i2c/busses/i2c-at91.c -@@ -1131,6 +1131,7 @@ static int at91_twi_suspend_noirq(struct device *dev) - - static int at91_twi_resume_noirq(struct device *dev) - { -+ struct at91_twi_dev *twi_dev = dev_get_drvdata(dev); - int ret; - - if (!pm_runtime_status_suspended(dev)) { -@@ -1142,6 +1143,8 @@ static int at91_twi_resume_noirq(struct device *dev) - pm_runtime_mark_last_busy(dev); - pm_request_autosuspend(dev); - -+ at91_init_twi_bus(twi_dev); -+ - return 0; - } - -diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c -index 02e636a1c49a..475c5a74f2d1 100644 ---- a/drivers/iio/adc/xilinx-xadc-core.c -+++ b/drivers/iio/adc/xilinx-xadc-core.c -@@ -1208,7 +1208,7 @@ static int xadc_probe(struct platform_device *pdev) - - ret = xadc->ops->setup(pdev, indio_dev, irq); - if (ret) -- goto err_free_samplerate_trigger; -+ goto err_clk_disable_unprepare; - - ret = request_irq(irq, xadc->ops->interrupt_handler, 0, - dev_name(&pdev->dev), indio_dev); -@@ -1268,6 +1268,8 @@ static int xadc_probe(struct platform_device *pdev) - - err_free_irq: - free_irq(irq, indio_dev); -+err_clk_disable_unprepare: -+ clk_disable_unprepare(xadc->clk); - err_free_samplerate_trigger: - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) - iio_trigger_free(xadc->samplerate_trigger); -@@ -1277,8 +1279,6 @@ err_free_convst_trigger: - err_triggered_buffer_cleanup: - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) - iio_triggered_buffer_cleanup(indio_dev); --err_clk_disable_unprepare: -- clk_disable_unprepare(xadc->clk); - err_device_free: - kfree(indio_dev->channels); - -diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c -index 75573fa431ba..63faee04a008 100644 ---- a/drivers/irqchip/irq-crossbar.c -+++ b/drivers/irqchip/irq-crossbar.c -@@ -198,7 +198,8 @@ static const struct irq_domain_ops crossbar_domain_ops = { - - static int __init crossbar_of_init(struct device_node *node) - { -- int i, size, max = 0, reserved = 0, entry; -+ int i, size, reserved = 0; -+ u32 max = 0, entry; - const __be32 *irqsr; - int ret = -ENOMEM; - -diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c -index bf3fbd00a091..64b586458d3d 100644 ---- a/drivers/isdn/i4l/isdn_ppp.c -+++ b/drivers/isdn/i4l/isdn_ppp.c -@@ -828,7 +828,6 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) - isdn_net_local *lp; - struct ippp_struct *is; - int proto; -- unsigned char protobuf[4]; - - is = file->private_data; - -@@ -842,24 +841,28 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) - if (!lp) - printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n"); - else { -- /* -- * Don't reset huptimer for -- * LCP packets. (Echo requests). -- */ -- if (copy_from_user(protobuf, buf, 4)) -- return -EFAULT; -- proto = PPP_PROTOCOL(protobuf); -- if (proto != PPP_LCP) -- lp->huptimer = 0; -+ if (lp->isdn_device < 0 || lp->isdn_channel < 0) { -+ unsigned char protobuf[4]; -+ /* -+ * Don't reset huptimer for -+ * LCP packets. (Echo requests). -+ */ -+ if (copy_from_user(protobuf, buf, 4)) -+ return -EFAULT; -+ -+ proto = PPP_PROTOCOL(protobuf); -+ if (proto != PPP_LCP) -+ lp->huptimer = 0; - -- if (lp->isdn_device < 0 || lp->isdn_channel < 0) - return 0; -+ } - - if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && - lp->dialstate == 0 && - (lp->flags & ISDN_NET_CONNECTED)) { - unsigned short hl; - struct sk_buff *skb; -+ unsigned char *cpy_buf; - /* - * we need to reserve enough space in front of - * sk_buff. old call to dev_alloc_skb only reserved -@@ -872,11 +875,21 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) - return count; - } - skb_reserve(skb, hl); -- if (copy_from_user(skb_put(skb, count), buf, count)) -+ cpy_buf = skb_put(skb, count); -+ if (copy_from_user(cpy_buf, buf, count)) - { - kfree_skb(skb); - return -EFAULT; - } -+ -+ /* -+ * Don't reset huptimer for -+ * LCP packets. (Echo requests). -+ */ -+ proto = PPP_PROTOCOL(cpy_buf); -+ if (proto != PPP_LCP) -+ lp->huptimer = 0; -+ - if (is->debug & 0x40) { - printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot); -diff --git a/drivers/md/linear.c b/drivers/md/linear.c -index 6ba3227e29b2..7ffb20ec1a46 100644 ---- a/drivers/md/linear.c -+++ b/drivers/md/linear.c -@@ -223,7 +223,8 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev) - * oldconf until no one uses it anymore. - */ - mddev_suspend(mddev); -- oldconf = rcu_dereference(mddev->private); -+ oldconf = rcu_dereference_protected(mddev->private, -+ lockdep_is_held(&mddev->reconfig_mutex)); - mddev->raid_disks++; - WARN_ONCE(mddev->raid_disks != newconf->raid_disks, - "copied raid_disks doesn't match mddev->raid_disks"); -diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c -index fdb5cdb3cd15..81abe46c9e0d 100644 ---- a/drivers/net/ethernet/ibm/emac/mal.c -+++ b/drivers/net/ethernet/ibm/emac/mal.c -@@ -402,7 +402,7 @@ static int mal_poll(struct napi_struct *napi, int budget) - unsigned long flags; - - MAL_DBG2(mal, "poll(%d)" NL, budget); -- again: -+ - /* Process TX skbs */ - list_for_each(l, &mal->poll_list) { - struct mal_commac *mc = -@@ -451,7 +451,6 @@ static int mal_poll(struct napi_struct *napi, int budget) - spin_lock_irqsave(&mal->lock, flags); - mal_disable_eob_irq(mal); - spin_unlock_irqrestore(&mal->lock, flags); -- goto again; - } - mc->ops->poll_tx(mc->dev); - } -diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c -index 0e67145bc418..4f34e1b79705 100644 ---- a/drivers/net/ethernet/marvell/mvpp2.c -+++ b/drivers/net/ethernet/marvell/mvpp2.c -@@ -4415,13 +4415,12 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port, - struct mvpp2_txq_pcpu_buf *tx_buf = - txq_pcpu->buffs + txq_pcpu->txq_get_index; - -- mvpp2_txq_inc_get(txq_pcpu); -- - dma_unmap_single(port->dev->dev.parent, tx_buf->phys, - tx_buf->size, DMA_TO_DEVICE); -- if (!tx_buf->skb) -- continue; -- dev_kfree_skb_any(tx_buf->skb); -+ if (tx_buf->skb) -+ dev_kfree_skb_any(tx_buf->skb); -+ -+ mvpp2_txq_inc_get(txq_pcpu); - } - } - -diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c -index 1494997c4f7e..4dccf7287f0f 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c -+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c -@@ -88,10 +88,17 @@ void mlx4_en_remove_timestamp(struct mlx4_en_dev *mdev) - } - } - -+#define MLX4_EN_WRAP_AROUND_SEC 10UL -+/* By scheduling the overflow check every 5 seconds, we have a reasonably -+ * good chance we wont miss a wrap around. -+ * TOTO: Use a timer instead of a work queue to increase the guarantee. -+ */ -+#define MLX4_EN_OVERFLOW_PERIOD (MLX4_EN_WRAP_AROUND_SEC * HZ / 2) -+ - void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev) - { - bool timeout = time_is_before_jiffies(mdev->last_overflow_check + -- mdev->overflow_period); -+ MLX4_EN_OVERFLOW_PERIOD); - unsigned long flags; - - if (timeout) { -@@ -236,7 +243,6 @@ static const struct ptp_clock_info mlx4_en_ptp_clock_info = { - .enable = mlx4_en_phc_enable, - }; - --#define MLX4_EN_WRAP_AROUND_SEC 10ULL - - /* This function calculates the max shift that enables the user range - * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register. -@@ -258,7 +264,6 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) - { - struct mlx4_dev *dev = mdev->dev; - unsigned long flags; -- u64 ns, zero = 0; - - /* mlx4_en_init_timestamp is called for each netdev. - * mdev->ptp_clock is common for all ports, skip initialization if -@@ -282,13 +287,6 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev) - ktime_to_ns(ktime_get_real())); - write_unlock_irqrestore(&mdev->clock_lock, flags); - -- /* Calculate period in seconds to call the overflow watchdog - to make -- * sure counter is checked at least once every wrap around. -- */ -- ns = cyclecounter_cyc2ns(&mdev->cycles, mdev->cycles.mask, zero, &zero); -- do_div(ns, NSEC_PER_SEC / 2 / HZ); -- mdev->overflow_period = ns; -- - /* Configure the PHC */ - mdev->ptp_clock_info = mlx4_en_ptp_clock_info; - snprintf(mdev->ptp_clock_info.name, 16, "mlx4 ptp"); -diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c -index 31c491e02e69..99361352ed0d 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/main.c -+++ b/drivers/net/ethernet/mellanox/mlx4/main.c -@@ -791,8 +791,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) - return -ENOSYS; - } - -- mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; -- - dev->caps.hca_core_clock = hca_param.hca_core_clock; - - memset(&dev_cap, 0, sizeof(dev_cap)); -diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -index c41f15102ae0..10aa6544cf4d 100644 ---- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h -@@ -409,7 +409,6 @@ struct mlx4_en_dev { - struct cyclecounter cycles; - struct timecounter clock; - unsigned long last_overflow_check; -- unsigned long overflow_period; - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_clock_info; - struct notifier_block nb; -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index c31d8e74f131..cd191f82d816 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -1195,11 +1195,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, - switch (tun->flags & TUN_TYPE_MASK) { - case IFF_TUN: - if (tun->flags & IFF_NO_PI) { -- switch (skb->data[0] & 0xf0) { -- case 0x40: -+ u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; -+ -+ switch (ip_version) { -+ case 4: - pi.proto = htons(ETH_P_IP); - break; -- case 0x60: -+ case 6: - pi.proto = htons(ETH_P_IPV6); - break; - default: -diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c -index 019d7165a045..2a996a68fc2b 100644 ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -2884,6 +2884,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, - static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) - { - struct hwsim_new_radio_params param = { 0 }; -+ const char *hwname = NULL; - - param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; - param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; -@@ -2897,8 +2898,14 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) - if (info->attrs[HWSIM_ATTR_NO_VIF]) - param.no_vif = true; - -- if (info->attrs[HWSIM_ATTR_RADIO_NAME]) -- param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); -+ if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { -+ hwname = kasprintf(GFP_KERNEL, "%.*s", -+ nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), -+ (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); -+ if (!hwname) -+ return -ENOMEM; -+ param.hwname = hwname; -+ } - - if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) - param.use_chanctx = true; -@@ -2926,11 +2933,15 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) - s64 idx = -1; - const char *hwname = NULL; - -- if (info->attrs[HWSIM_ATTR_RADIO_ID]) -+ if (info->attrs[HWSIM_ATTR_RADIO_ID]) { - idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); -- else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) -- hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); -- else -+ } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { -+ hwname = kasprintf(GFP_KERNEL, "%.*s", -+ nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), -+ (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); -+ if (!hwname) -+ return -ENOMEM; -+ } else - return -EINVAL; - - spin_lock_bh(&hwsim_radio_lock); -@@ -2939,7 +2950,8 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) - if (data->idx != idx) - continue; - } else { -- if (strcmp(hwname, wiphy_name(data->hw->wiphy))) -+ if (!hwname || -+ strcmp(hwname, wiphy_name(data->hw->wiphy))) - continue; - } - -@@ -2947,10 +2959,12 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) - spin_unlock_bh(&hwsim_radio_lock); - mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), - info); -+ kfree(hwname); - return 0; - } - spin_unlock_bh(&hwsim_radio_lock); - -+ kfree(hwname); - return -ENODEV; - } - -diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c -index e6fb97cb12f4..7c28dc1cb0dd 100644 ---- a/drivers/scsi/device_handler/scsi_dh_emc.c -+++ b/drivers/scsi/device_handler/scsi_dh_emc.c -@@ -456,7 +456,7 @@ static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) - static int clariion_std_inquiry(struct scsi_device *sdev, - struct clariion_dh_data *csdev) - { -- int err; -+ int err = SCSI_DH_OK; - char *sp_model; - - err = send_inquiry_cmd(sdev, 0, csdev); -diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c -index 6c88fb021444..4eeb82cf79e4 100644 ---- a/drivers/target/iscsi/iscsi_target_erl0.c -+++ b/drivers/target/iscsi/iscsi_target_erl0.c -@@ -44,10 +44,8 @@ void iscsit_set_dataout_sequence_values( - */ - if (cmd->unsolicited_data) { - cmd->seq_start_offset = cmd->write_data_done; -- cmd->seq_end_offset = (cmd->write_data_done + -- ((cmd->se_cmd.data_length > -- conn->sess->sess_ops->FirstBurstLength) ? -- conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length)); -+ cmd->seq_end_offset = min(cmd->se_cmd.data_length, -+ conn->sess->sess_ops->FirstBurstLength); - return; - } - -diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c -index e04b57f79df8..0f82c0b146f6 100644 ---- a/drivers/tty/goldfish.c -+++ b/drivers/tty/goldfish.c -@@ -293,7 +293,7 @@ static int goldfish_tty_probe(struct platform_device *pdev) - return 0; - - err_tty_register_device_failed: -- free_irq(irq, qtty); -+ free_irq(irq, pdev); - err_request_irq_failed: - goldfish_tty_current_line_count--; - if (goldfish_tty_current_line_count == 0) -diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c -index 4e603d060e80..59828d819145 100644 ---- a/drivers/tty/serial/sunhv.c -+++ b/drivers/tty/serial/sunhv.c -@@ -398,6 +398,12 @@ static struct uart_driver sunhv_reg = { - - static struct uart_port *sunhv_port; - -+void sunhv_migrate_hvcons_irq(int cpu) -+{ -+ /* Migrate hvcons irq to param cpu */ -+ irq_force_affinity(sunhv_port->irq, cpumask_of(cpu)); -+} -+ - /* Copy 's' into the con_write_page, decoding "\n" into - * "\r\n" along the way. We have to return two lengths - * because the caller needs to know how much to advance -diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c -index 5bf931ce1353..978098f71761 100644 ---- a/drivers/watchdog/kempld_wdt.c -+++ b/drivers/watchdog/kempld_wdt.c -@@ -140,12 +140,19 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data, - unsigned int timeout) - { - struct kempld_device_data *pld = wdt_data->pld; -- u32 prescaler = kempld_prescaler[PRESCALER_21]; -+ u32 prescaler; - u64 stage_timeout64; - u32 stage_timeout; - u32 remainder; - u8 stage_cfg; - -+#if GCC_VERSION < 40400 -+ /* work around a bug compiling do_div() */ -+ prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]); -+#else -+ prescaler = kempld_prescaler[PRESCALER_21]; -+#endif -+ - if (!stage) - return -EINVAL; - -diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c -index 63a6152be04b..c5bbb5300658 100644 ---- a/fs/btrfs/send.c -+++ b/fs/btrfs/send.c -@@ -1648,6 +1648,9 @@ static int is_inode_existent(struct send_ctx *sctx, u64 ino, u64 gen) - { - int ret; - -+ if (ino == BTRFS_FIRST_FREE_OBJECTID) -+ return 1; -+ - ret = get_cur_inode_state(sctx, ino, gen); - if (ret < 0) - goto out; -@@ -1833,7 +1836,7 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen, - * not delted and then re-created, if it was then we have no overwrite - * and we can just unlink this entry. - */ -- if (sctx->parent_root) { -+ if (sctx->parent_root && dir != BTRFS_FIRST_FREE_OBJECTID) { - ret = get_inode_info(sctx->parent_root, dir, NULL, &gen, NULL, - NULL, NULL, NULL); - if (ret < 0 && ret != -ENOENT) -diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c -index f54f77037d22..ead89489ae71 100644 ---- a/fs/ceph/mds_client.c -+++ b/fs/ceph/mds_client.c -@@ -1845,13 +1845,18 @@ static int build_dentry_path(struct dentry *dentry, - int *pfreepath) - { - char *path; -+ struct inode *dir; - -- if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_NOSNAP) { -- *pino = ceph_ino(d_inode(dentry->d_parent)); -+ rcu_read_lock(); -+ dir = d_inode_rcu(dentry->d_parent); -+ if (dir && ceph_snap(dir) == CEPH_NOSNAP) { -+ *pino = ceph_ino(dir); -+ rcu_read_unlock(); - *ppath = dentry->d_name.name; - *ppathlen = dentry->d_name.len; - return 0; - } -+ rcu_read_unlock(); - path = ceph_mdsc_build_path(dentry, ppathlen, pino, 1); - if (IS_ERR(path)) - return PTR_ERR(path); -diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c -index 972eab7ac071..98b2fc2678ff 100644 ---- a/fs/f2fs/data.c -+++ b/fs/f2fs/data.c -@@ -1416,7 +1416,12 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, - goto fail; - } - repeat: -- page = grab_cache_page_write_begin(mapping, index, flags); -+ /* -+ * Do not use grab_cache_page_write_begin() to avoid deadlock due to -+ * wait_for_stable_page. Will wait that below with our IO control. -+ */ -+ page = pagecache_get_page(mapping, index, -+ FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS); - if (!page) { - err = -ENOMEM; - goto fail; -diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c -index 15bdc2d48cfe..24ace275160c 100644 ---- a/fs/nfsd/nfs4callback.c -+++ b/fs/nfsd/nfs4callback.c -@@ -696,6 +696,14 @@ int set_callback_cred(void) - return 0; - } - -+void cleanup_callback_cred(void) -+{ -+ if (callback_cred) { -+ put_rpccred(callback_cred); -+ callback_cred = NULL; -+ } -+} -+ - static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) - { - if (clp->cl_minorversion == 0) { -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index 9e5a6842346e..ca9ebc3242d3 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -6792,23 +6792,24 @@ nfs4_state_start(void) - - ret = set_callback_cred(); - if (ret) -- return -ENOMEM; -+ return ret; -+ - laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4"); - if (laundry_wq == NULL) { - ret = -ENOMEM; -- goto out_recovery; -+ goto out_cleanup_cred; - } - ret = nfsd4_create_callback_queue(); - if (ret) - goto out_free_laundry; - - set_max_delegations(); -- - return 0; - - out_free_laundry: - destroy_workqueue(laundry_wq); --out_recovery: -+out_cleanup_cred: -+ cleanup_callback_cred(); - return ret; - } - -@@ -6847,6 +6848,7 @@ nfs4_state_shutdown(void) - { - destroy_workqueue(laundry_wq); - nfsd4_destroy_callback_queue(); -+ cleanup_callback_cred(); - } - - static void -diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h -index 5134eedcb16c..86af697c21d3 100644 ---- a/fs/nfsd/state.h -+++ b/fs/nfsd/state.h -@@ -595,6 +595,7 @@ extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, - extern __be32 nfs4_check_open_reclaim(clientid_t *clid, - struct nfsd4_compound_state *cstate, struct nfsd_net *nn); - extern int set_callback_cred(void); -+extern void cleanup_callback_cred(void); - extern void nfsd4_probe_callback(struct nfs4_client *clp); - extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); - extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); -diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c -index 60a5f1548cd9..555b57a16499 100644 ---- a/fs/ocfs2/dlmglue.c -+++ b/fs/ocfs2/dlmglue.c -@@ -531,6 +531,7 @@ void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) - init_waitqueue_head(&res->l_event); - INIT_LIST_HEAD(&res->l_blocked_list); - INIT_LIST_HEAD(&res->l_mask_waiters); -+ INIT_LIST_HEAD(&res->l_holders); - } - - void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, -@@ -748,6 +749,50 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res) - res->l_flags = 0UL; - } - -+/* -+ * Keep a list of processes who have interest in a lockres. -+ * Note: this is now only uesed for check recursive cluster locking. -+ */ -+static inline void ocfs2_add_holder(struct ocfs2_lock_res *lockres, -+ struct ocfs2_lock_holder *oh) -+{ -+ INIT_LIST_HEAD(&oh->oh_list); -+ oh->oh_owner_pid = get_pid(task_pid(current)); -+ -+ spin_lock(&lockres->l_lock); -+ list_add_tail(&oh->oh_list, &lockres->l_holders); -+ spin_unlock(&lockres->l_lock); -+} -+ -+static inline void ocfs2_remove_holder(struct ocfs2_lock_res *lockres, -+ struct ocfs2_lock_holder *oh) -+{ -+ spin_lock(&lockres->l_lock); -+ list_del(&oh->oh_list); -+ spin_unlock(&lockres->l_lock); -+ -+ put_pid(oh->oh_owner_pid); -+} -+ -+static inline int ocfs2_is_locked_by_me(struct ocfs2_lock_res *lockres) -+{ -+ struct ocfs2_lock_holder *oh; -+ struct pid *pid; -+ -+ /* look in the list of holders for one with the current task as owner */ -+ spin_lock(&lockres->l_lock); -+ pid = task_pid(current); -+ list_for_each_entry(oh, &lockres->l_holders, oh_list) { -+ if (oh->oh_owner_pid == pid) { -+ spin_unlock(&lockres->l_lock); -+ return 1; -+ } -+ } -+ spin_unlock(&lockres->l_lock); -+ -+ return 0; -+} -+ - static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, - int level) - { -@@ -2343,8 +2388,9 @@ int ocfs2_inode_lock_full_nested(struct inode *inode, - goto getbh; - } - -- if (ocfs2_mount_local(osb)) -- goto local; -+ if ((arg_flags & OCFS2_META_LOCK_GETBH) || -+ ocfs2_mount_local(osb)) -+ goto update; - - if (!(arg_flags & OCFS2_META_LOCK_RECOVERY)) - ocfs2_wait_for_recovery(osb); -@@ -2373,7 +2419,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode, - if (!(arg_flags & OCFS2_META_LOCK_RECOVERY)) - ocfs2_wait_for_recovery(osb); - --local: -+update: - /* - * We only see this flag if we're being called from - * ocfs2_read_locked_inode(). It means we're locking an inode -@@ -2515,6 +2561,59 @@ void ocfs2_inode_unlock(struct inode *inode, - ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); - } - -+/* -+ * This _tracker variantes are introduced to deal with the recursive cluster -+ * locking issue. The idea is to keep track of a lock holder on the stack of -+ * the current process. If there's a lock holder on the stack, we know the -+ * task context is already protected by cluster locking. Currently, they're -+ * used in some VFS entry routines. -+ * -+ * return < 0 on error, return == 0 if there's no lock holder on the stack -+ * before this call, return == 1 if this call would be a recursive locking. -+ */ -+int ocfs2_inode_lock_tracker(struct inode *inode, -+ struct buffer_head **ret_bh, -+ int ex, -+ struct ocfs2_lock_holder *oh) -+{ -+ int status; -+ int arg_flags = 0, has_locked; -+ struct ocfs2_lock_res *lockres; -+ -+ lockres = &OCFS2_I(inode)->ip_inode_lockres; -+ has_locked = ocfs2_is_locked_by_me(lockres); -+ /* Just get buffer head if the cluster lock has been taken */ -+ if (has_locked) -+ arg_flags = OCFS2_META_LOCK_GETBH; -+ -+ if (likely(!has_locked || ret_bh)) { -+ status = ocfs2_inode_lock_full(inode, ret_bh, ex, arg_flags); -+ if (status < 0) { -+ if (status != -ENOENT) -+ mlog_errno(status); -+ return status; -+ } -+ } -+ if (!has_locked) -+ ocfs2_add_holder(lockres, oh); -+ -+ return has_locked; -+} -+ -+void ocfs2_inode_unlock_tracker(struct inode *inode, -+ int ex, -+ struct ocfs2_lock_holder *oh, -+ int had_lock) -+{ -+ struct ocfs2_lock_res *lockres; -+ -+ lockres = &OCFS2_I(inode)->ip_inode_lockres; -+ if (!had_lock) { -+ ocfs2_remove_holder(lockres, oh); -+ ocfs2_inode_unlock(inode, ex); -+ } -+} -+ - int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno) - { - struct ocfs2_lock_res *lockres; -diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h -index d293a22c32c5..a7fc18ba0dc1 100644 ---- a/fs/ocfs2/dlmglue.h -+++ b/fs/ocfs2/dlmglue.h -@@ -70,6 +70,11 @@ struct ocfs2_orphan_scan_lvb { - __be32 lvb_os_seqno; - }; - -+struct ocfs2_lock_holder { -+ struct list_head oh_list; -+ struct pid *oh_owner_pid; -+}; -+ - /* ocfs2_inode_lock_full() 'arg_flags' flags */ - /* don't wait on recovery. */ - #define OCFS2_META_LOCK_RECOVERY (0x01) -@@ -77,6 +82,8 @@ struct ocfs2_orphan_scan_lvb { - #define OCFS2_META_LOCK_NOQUEUE (0x02) - /* don't block waiting for the downconvert thread, instead return -EAGAIN */ - #define OCFS2_LOCK_NONBLOCK (0x04) -+/* just get back disk inode bh if we've got cluster lock. */ -+#define OCFS2_META_LOCK_GETBH (0x08) - - /* Locking subclasses of inode cluster lock */ - enum { -@@ -170,4 +177,15 @@ void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug); - - /* To set the locking protocol on module initialization */ - void ocfs2_set_locking_protocol(void); -+ -+/* The _tracker pair is used to avoid cluster recursive locking */ -+int ocfs2_inode_lock_tracker(struct inode *inode, -+ struct buffer_head **ret_bh, -+ int ex, -+ struct ocfs2_lock_holder *oh); -+void ocfs2_inode_unlock_tracker(struct inode *inode, -+ int ex, -+ struct ocfs2_lock_holder *oh, -+ int had_lock); -+ - #endif /* DLMGLUE_H */ -diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h -index 7a0126267847..2495066a9ca3 100644 ---- a/fs/ocfs2/ocfs2.h -+++ b/fs/ocfs2/ocfs2.h -@@ -172,6 +172,7 @@ struct ocfs2_lock_res { - - struct list_head l_blocked_list; - struct list_head l_mask_waiters; -+ struct list_head l_holders; - - unsigned long l_flags; - char l_name[OCFS2_LOCK_ID_MAX_LEN]; -diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h -index 4d9f233c4ba8..7d58ffdacd62 100644 ---- a/include/asm-generic/percpu.h -+++ b/include/asm-generic/percpu.h -@@ -105,15 +105,35 @@ do { \ - (__ret); \ - }) - --#define this_cpu_generic_read(pcp) \ -+#define __this_cpu_generic_read_nopreempt(pcp) \ - ({ \ - typeof(pcp) __ret; \ - preempt_disable(); \ -- __ret = *this_cpu_ptr(&(pcp)); \ -+ __ret = READ_ONCE(*raw_cpu_ptr(&(pcp))); \ - preempt_enable(); \ - __ret; \ - }) - -+#define __this_cpu_generic_read_noirq(pcp) \ -+({ \ -+ typeof(pcp) __ret; \ -+ unsigned long __flags; \ -+ raw_local_irq_save(__flags); \ -+ __ret = *raw_cpu_ptr(&(pcp)); \ -+ raw_local_irq_restore(__flags); \ -+ __ret; \ -+}) -+ -+#define this_cpu_generic_read(pcp) \ -+({ \ -+ typeof(pcp) __ret; \ -+ if (__native_word(pcp)) \ -+ __ret = __this_cpu_generic_read_nopreempt(pcp); \ -+ else \ -+ __ret = __this_cpu_generic_read_noirq(pcp); \ -+ __ret; \ -+}) -+ - #define this_cpu_generic_to_op(pcp, val, op) \ - do { \ - unsigned long __flags; \ -diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h -index 925730bc9fc1..311176f290b2 100644 ---- a/include/linux/trace_events.h -+++ b/include/linux/trace_events.h -@@ -301,6 +301,7 @@ struct trace_event_call { - int perf_refcount; - struct hlist_head __percpu *perf_events; - struct bpf_prog *prog; -+ struct perf_event *bpf_prog_owner; - - int (*perf_perm)(struct trace_event_call *, - struct perf_event *); -diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h -index cccdcfd14973..f348c736e6e0 100644 ---- a/include/net/sctp/ulpevent.h -+++ b/include/net/sctp/ulpevent.h -@@ -141,8 +141,12 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); - static inline int sctp_ulpevent_type_enabled(__u16 sn_type, - struct sctp_event_subscribe *mask) - { -+ int offset = sn_type - SCTP_SN_TYPE_BASE; - char *amask = (char *) mask; -- return amask[sn_type - SCTP_SN_TYPE_BASE]; -+ -+ if (offset >= sizeof(struct sctp_event_subscribe)) -+ return 0; -+ return amask[offset]; - } - - /* Given an event subscription, is this event enabled? */ -diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h -index ce91215cf7e6..e0b566dc72ef 100644 ---- a/include/uapi/linux/mroute6.h -+++ b/include/uapi/linux/mroute6.h -@@ -3,6 +3,7 @@ - - #include - #include -+#include /* For struct sockaddr_in6. */ - - /* - * Based on the MROUTING 3.5 defines primarily to keep -diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h -index 0f9265cb2a96..7af20a136429 100644 ---- a/include/uapi/linux/rds.h -+++ b/include/uapi/linux/rds.h -@@ -35,6 +35,7 @@ - #define _LINUX_RDS_H - - #include -+#include /* For __kernel_sockaddr_storage. */ - - #define RDS_IB_ABI_VERSION 0x301 - -@@ -223,7 +224,7 @@ struct rds_get_mr_args { - }; - - struct rds_get_mr_for_dest_args { -- struct sockaddr_storage dest_addr; -+ struct __kernel_sockaddr_storage dest_addr; - struct rds_iovec vec; - uint64_t cookie_addr; - uint64_t flags; -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index 863e24f1e62e..70dc6dcf8649 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -1033,7 +1033,8 @@ static int check_alu_op(struct verifier_env *env, struct bpf_insn *insn) - } - } else { - if (insn->src_reg != BPF_REG_0 || insn->off != 0 || -- (insn->imm != 16 && insn->imm != 32 && insn->imm != 64)) { -+ (insn->imm != 16 && insn->imm != 32 && insn->imm != 64) || -+ BPF_CLASS(insn->code) == BPF_ALU64) { - verbose("BPF_END uses reserved fields\n"); - return -EINVAL; - } -diff --git a/kernel/events/core.c b/kernel/events/core.c -index 3697063dd09a..8f75386e61a7 100644 ---- a/kernel/events/core.c -+++ b/kernel/events/core.c -@@ -7108,6 +7108,7 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd) - } - - event->tp_event->prog = prog; -+ event->tp_event->bpf_prog_owner = event; - - return 0; - } -@@ -7120,7 +7121,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event) - return; - - prog = event->tp_event->prog; -- if (prog) { -+ if (prog && event->tp_event->bpf_prog_owner == event) { - event->tp_event->prog = NULL; - bpf_prog_put_rcu(prog); - } -diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index 60ace56618f6..0e2c4911ba61 100644 ---- a/kernel/locking/lockdep.c -+++ b/kernel/locking/lockdep.c -@@ -3128,10 +3128,17 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, - if (depth) { - hlock = curr->held_locks + depth - 1; - if (hlock->class_idx == class_idx && nest_lock) { -- if (hlock->references) -+ if (hlock->references) { -+ /* -+ * Check: unsigned int references:12, overflow. -+ */ -+ if (DEBUG_LOCKS_WARN_ON(hlock->references == (1 << 12)-1)) -+ return 0; -+ - hlock->references++; -- else -+ } else { - hlock->references = 2; -+ } - - return 1; - } -diff --git a/mm/slab_common.c b/mm/slab_common.c -index bec2fce9fafc..01e7246de8df 100644 ---- a/mm/slab_common.c -+++ b/mm/slab_common.c -@@ -250,7 +250,7 @@ struct kmem_cache *find_mergeable(size_t size, size_t align, - { - struct kmem_cache *s; - -- if (slab_nomerge || (flags & SLAB_NEVER_MERGE)) -+ if (slab_nomerge) - return NULL; - - if (ctor) -@@ -261,6 +261,9 @@ struct kmem_cache *find_mergeable(size_t size, size_t align, - size = ALIGN(size, align); - flags = kmem_cache_flags(size, flags, name, NULL); - -+ if (flags & SLAB_NEVER_MERGE) -+ return NULL; -+ - list_for_each_entry_reverse(s, &slab_caches, list) { - if (slab_unmergeable(s)) - continue; -diff --git a/net/core/sock.c b/net/core/sock.c -index bd2fad27891e..cd12cb6fe366 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -1516,6 +1516,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) - - sock_copy(newsk, sk); - -+ newsk->sk_prot_creator = sk->sk_prot; -+ - /* SANITY */ - if (likely(newsk->sk_net_refcnt)) - get_net(sock_net(newsk)); -diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c -index 65036891e080..a03f834f16d5 100644 ---- a/net/ipv4/ip_vti.c -+++ b/net/ipv4/ip_vti.c -@@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, - struct ip_tunnel_parm *parms = &tunnel->parms; - struct dst_entry *dst = skb_dst(skb); - struct net_device *tdev; /* Device to other host */ -+ int pkt_len = skb->len; - int err; - - if (!dst) { -@@ -199,7 +200,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, - - err = dst_output(tunnel->net, skb->sk, skb); - if (net_xmit_eval(err) == 0) -- err = skb->len; -+ err = pkt_len; - iptunnel_xmit_stats(err, &dev->stats, dev->tstats); - return NETDEV_TX_OK; - -diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c -index e89135828c3d..eab117033b8a 100644 ---- a/net/ipv6/ip6_gre.c -+++ b/net/ipv6/ip6_gre.c -@@ -1173,24 +1173,25 @@ static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu) - } - - static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, -- unsigned short type, -- const void *daddr, const void *saddr, unsigned int len) -+ unsigned short type, const void *daddr, -+ const void *saddr, unsigned int len) - { - struct ip6_tnl *t = netdev_priv(dev); -- struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); -- __be16 *p = (__be16 *)(ipv6h+1); -+ struct ipv6hdr *ipv6h; -+ __be16 *p; - -- ip6_flow_hdr(ipv6h, 0, -- ip6_make_flowlabel(dev_net(dev), skb, -- t->fl.u.ip6.flowlabel, true, -- &t->fl.u.ip6)); -+ ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen + sizeof(*ipv6h)); -+ ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, -+ t->fl.u.ip6.flowlabel, -+ true, &t->fl.u.ip6)); - ipv6h->hop_limit = t->parms.hop_limit; - ipv6h->nexthdr = NEXTHDR_GRE; - ipv6h->saddr = t->parms.laddr; - ipv6h->daddr = t->parms.raddr; - -- p[0] = t->parms.o_flags; -- p[1] = htons(type); -+ p = (__be16 *)(ipv6h + 1); -+ p[0] = t->parms.o_flags; -+ p[1] = htons(type); - - /* - * Set the source hardware address. -diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c -index bdcc4d9cedd3..7ebb14def2cb 100644 ---- a/net/ipv6/ip6_vti.c -+++ b/net/ipv6/ip6_vti.c -@@ -434,6 +434,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) - struct dst_entry *dst = skb_dst(skb); - struct net_device *tdev; - struct xfrm_state *x; -+ int pkt_len = skb->len; - int err = -1; - int mtu; - -@@ -487,7 +488,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) - struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); - - u64_stats_update_begin(&tstats->syncp); -- tstats->tx_bytes += skb->len; -+ tstats->tx_bytes += pkt_len; - tstats->tx_packets++; - u64_stats_update_end(&tstats->syncp); - } else { -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 6fd4af3b5b79..6eb1e9293b6f 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -1007,6 +1007,7 @@ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, - */ - offset = skb_transport_offset(skb); - skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); -+ csum = skb->csum; - - skb->ip_summed = CHECKSUM_NONE; - -diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c -index d3dec414fd44..d48281ca9c72 100644 ---- a/net/l2tp/l2tp_core.c -+++ b/net/l2tp/l2tp_core.c -@@ -1321,6 +1321,9 @@ static void l2tp_tunnel_del_work(struct work_struct *work) - struct sock *sk = NULL; - - tunnel = container_of(work, struct l2tp_tunnel, del_work); -+ -+ l2tp_tunnel_closeall(tunnel); -+ - sk = l2tp_tunnel_sock_lookup(tunnel); - if (!sk) - goto out; -@@ -1640,15 +1643,12 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); - - /* This function is used by the netlink TUNNEL_DELETE command. - */ --int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) -+void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) - { -- l2tp_tunnel_inc_refcount(tunnel); -- l2tp_tunnel_closeall(tunnel); -- if (false == queue_work(l2tp_wq, &tunnel->del_work)) { -- l2tp_tunnel_dec_refcount(tunnel); -- return 1; -+ if (!test_and_set_bit(0, &tunnel->dead)) { -+ l2tp_tunnel_inc_refcount(tunnel); -+ queue_work(l2tp_wq, &tunnel->del_work); - } -- return 0; - } - EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); - -diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h -index 555d962a62d2..9cf546846edb 100644 ---- a/net/l2tp/l2tp_core.h -+++ b/net/l2tp/l2tp_core.h -@@ -169,6 +169,9 @@ struct l2tp_tunnel_cfg { - - struct l2tp_tunnel { - int magic; /* Should be L2TP_TUNNEL_MAGIC */ -+ -+ unsigned long dead; -+ - struct rcu_head rcu; - rwlock_t hlist_lock; /* protect session_hlist */ - struct hlist_head session_hlist[L2TP_HASH_SIZE]; -@@ -253,7 +256,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, - u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, - struct l2tp_tunnel **tunnelp); - void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); --int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); -+void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); - struct l2tp_session *l2tp_session_create(int priv_size, - struct l2tp_tunnel *tunnel, - u32 session_id, u32 peer_session_id, -diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c -index 63ea6cbac5ad..7e7b9ef29d8d 100644 ---- a/net/mac80211/sta_info.c -+++ b/net/mac80211/sta_info.c -@@ -661,7 +661,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending) - } - - /* No need to do anything if the driver does all */ -- if (ieee80211_hw_check(&local->hw, AP_LINK_PS)) -+ if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim) - return; - - if (sta->dead) -diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c -index acf5c7b3f378..7f16d19d6198 100644 ---- a/net/netfilter/nf_conntrack_expect.c -+++ b/net/netfilter/nf_conntrack_expect.c -@@ -395,7 +395,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) - struct net *net = nf_ct_exp_net(expect); - struct hlist_node *next; - unsigned int h; -- int ret = 1; -+ int ret = 0; - - if (!master_help) { - ret = -ESHUTDOWN; -@@ -445,7 +445,7 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, - - spin_lock_bh(&nf_conntrack_expect_lock); - ret = __nf_ct_expect_check(expect); -- if (ret <= 0) -+ if (ret < 0) - goto out; - - ret = nf_ct_expect_insert(expect); -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index b70055fc30cb..241f69039a72 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -1652,10 +1652,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - - mutex_lock(&fanout_mutex); - -- err = -EINVAL; -- if (!po->running) -- goto out; -- - err = -EALREADY; - if (po->fanout) - goto out; -@@ -1704,7 +1700,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - list_add(&match->list, &fanout_list); - } - err = -EINVAL; -- if (match->type == type && -+ -+ spin_lock(&po->bind_lock); -+ if (po->running && -+ match->type == type && - match->prot_hook.type == po->prot_hook.type && - match->prot_hook.dev == po->prot_hook.dev) { - err = -ENOSPC; -@@ -1716,6 +1715,13 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - err = 0; - } - } -+ spin_unlock(&po->bind_lock); -+ -+ if (err && !atomic_read(&match->sk_ref)) { -+ list_del(&match->list); -+ kfree(match); -+ } -+ - out: - if (err && rollover) { - kfree(rollover); -@@ -2650,6 +2656,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) - int vnet_hdr_len; - struct packet_sock *po = pkt_sk(sk); - unsigned short gso_type = 0; -+ bool has_vnet_hdr = false; - int hlen, tlen, linear; - int extra_len = 0; - ssize_t n; -@@ -2737,6 +2744,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) - goto out_unlock; - - } -+ has_vnet_hdr = true; - } - - if (unlikely(sock_flag(sk, SOCK_NOFCS))) { -@@ -2796,7 +2804,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) - - packet_pick_tx_queue(dev, skb); - -- if (po->has_vnet_hdr) { -+ if (has_vnet_hdr) { - if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start); - u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset); -@@ -2938,13 +2946,15 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, - int ret = 0; - bool unlisted = false; - -- if (po->fanout) -- return -EINVAL; -- - lock_sock(sk); - spin_lock(&po->bind_lock); - rcu_read_lock(); - -+ if (po->fanout) { -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ - if (name) { - dev = dev_get_by_name_rcu(sock_net(sk), name); - if (!dev) { -diff --git a/net/tipc/msg.c b/net/tipc/msg.c -index 8740930f0787..67bddcb2ff46 100644 ---- a/net/tipc/msg.c -+++ b/net/tipc/msg.c -@@ -541,7 +541,7 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err) - return false; - if (msg_errcode(msg)) - return false; -- *err = -TIPC_ERR_NO_NAME; -+ *err = TIPC_ERR_NO_NAME; - if (skb_linearize(skb)) - return false; - msg = buf_msg(skb); diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.94-95.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.94-95.patch deleted file mode 100644 index d5f069211..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.94-95.patch +++ /dev/null @@ -1,1587 +0,0 @@ -diff --git a/Makefile b/Makefile -index ff9d6bbf2210..57e1ea2a189a 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 94 -+SUBLEVEL = 95 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S -index a86b19fccb63..c6b855f7892c 100644 ---- a/arch/parisc/kernel/syscall.S -+++ b/arch/parisc/kernel/syscall.S -@@ -479,11 +479,6 @@ lws_start: - comiclr,>> __NR_lws_entries, %r20, %r0 - b,n lws_exit_nosys - -- /* WARNING: Trashing sr2 and sr3 */ -- mfsp %sr7,%r1 /* get userspace into sr3 */ -- mtsp %r1,%sr3 -- mtsp %r0,%sr2 /* get kernel space into sr2 */ -- - /* Load table start */ - ldil L%lws_table, %r1 - ldo R%lws_table(%r1), %r28 /* Scratch use of r28 */ -@@ -632,9 +627,9 @@ cas_action: - stw %r1, 4(%sr2,%r20) - #endif - /* The load and store could fail */ --1: ldw,ma 0(%sr3,%r26), %r28 -+1: ldw,ma 0(%r26), %r28 - sub,<> %r28, %r25, %r0 --2: stw,ma %r24, 0(%sr3,%r26) -+2: stw,ma %r24, 0(%r26) - /* Free lock */ - stw,ma %r20, 0(%sr2,%r20) - #if ENABLE_LWS_DEBUG -@@ -711,9 +706,9 @@ lws_compare_and_swap_2: - nop - - /* 8bit load */ --4: ldb 0(%sr3,%r25), %r25 -+4: ldb 0(%r25), %r25 - b cas2_lock_start --5: ldb 0(%sr3,%r24), %r24 -+5: ldb 0(%r24), %r24 - nop - nop - nop -@@ -721,9 +716,9 @@ lws_compare_and_swap_2: - nop - - /* 16bit load */ --6: ldh 0(%sr3,%r25), %r25 -+6: ldh 0(%r25), %r25 - b cas2_lock_start --7: ldh 0(%sr3,%r24), %r24 -+7: ldh 0(%r24), %r24 - nop - nop - nop -@@ -731,9 +726,9 @@ lws_compare_and_swap_2: - nop - - /* 32bit load */ --8: ldw 0(%sr3,%r25), %r25 -+8: ldw 0(%r25), %r25 - b cas2_lock_start --9: ldw 0(%sr3,%r24), %r24 -+9: ldw 0(%r24), %r24 - nop - nop - nop -@@ -742,14 +737,14 @@ lws_compare_and_swap_2: - - /* 64bit load */ - #ifdef CONFIG_64BIT --10: ldd 0(%sr3,%r25), %r25 --11: ldd 0(%sr3,%r24), %r24 -+10: ldd 0(%r25), %r25 -+11: ldd 0(%r24), %r24 - #else -- /* Load new value into r22/r23 - high/low */ --10: ldw 0(%sr3,%r25), %r22 --11: ldw 4(%sr3,%r25), %r23 -+ /* Load old value into r22/r23 - high/low */ -+10: ldw 0(%r25), %r22 -+11: ldw 4(%r25), %r23 - /* Load new value into fr4 for atomic store later */ --12: flddx 0(%sr3,%r24), %fr4 -+12: flddx 0(%r24), %fr4 - #endif - - cas2_lock_start: -@@ -799,30 +794,30 @@ cas2_action: - ldo 1(%r0),%r28 - - /* 8bit CAS */ --13: ldb,ma 0(%sr3,%r26), %r29 -+13: ldb,ma 0(%r26), %r29 - sub,= %r29, %r25, %r0 - b,n cas2_end --14: stb,ma %r24, 0(%sr3,%r26) -+14: stb,ma %r24, 0(%r26) - b cas2_end - copy %r0, %r28 - nop - nop - - /* 16bit CAS */ --15: ldh,ma 0(%sr3,%r26), %r29 -+15: ldh,ma 0(%r26), %r29 - sub,= %r29, %r25, %r0 - b,n cas2_end --16: sth,ma %r24, 0(%sr3,%r26) -+16: sth,ma %r24, 0(%r26) - b cas2_end - copy %r0, %r28 - nop - nop - - /* 32bit CAS */ --17: ldw,ma 0(%sr3,%r26), %r29 -+17: ldw,ma 0(%r26), %r29 - sub,= %r29, %r25, %r0 - b,n cas2_end --18: stw,ma %r24, 0(%sr3,%r26) -+18: stw,ma %r24, 0(%r26) - b cas2_end - copy %r0, %r28 - nop -@@ -830,22 +825,22 @@ cas2_action: - - /* 64bit CAS */ - #ifdef CONFIG_64BIT --19: ldd,ma 0(%sr3,%r26), %r29 -+19: ldd,ma 0(%r26), %r29 - sub,*= %r29, %r25, %r0 - b,n cas2_end --20: std,ma %r24, 0(%sr3,%r26) -+20: std,ma %r24, 0(%r26) - copy %r0, %r28 - #else - /* Compare first word */ --19: ldw,ma 0(%sr3,%r26), %r29 -+19: ldw 0(%r26), %r29 - sub,= %r29, %r22, %r0 - b,n cas2_end - /* Compare second word */ --20: ldw,ma 4(%sr3,%r26), %r29 -+20: ldw 4(%r26), %r29 - sub,= %r29, %r23, %r0 - b,n cas2_end - /* Perform the store */ --21: fstdx %fr4, 0(%sr3,%r26) -+21: fstdx %fr4, 0(%r26) - copy %r0, %r28 - #endif - -diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c -index 8f3056cd0399..2516e97c58f1 100644 ---- a/crypto/asymmetric_keys/pkcs7_parser.c -+++ b/crypto/asymmetric_keys/pkcs7_parser.c -@@ -90,6 +90,9 @@ static int pkcs7_check_authattrs(struct pkcs7_message *msg) - bool want; - - sinfo = msg->signed_infos; -+ if (!sinfo) -+ goto inconsistent; -+ - if (sinfo->authattrs) { - want = true; - msg->have_authattrs = true; -diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c -index c43c3d2baf73..0d628becf37f 100644 ---- a/drivers/bus/mvebu-mbus.c -+++ b/drivers/bus/mvebu-mbus.c -@@ -720,7 +720,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) - if (mbus->hw_io_coherency) - w->mbus_attr |= ATTR_HW_COHERENCY; - w->base = base & DDR_BASE_CS_LOW_MASK; -- w->size = (size | ~DDR_SIZE_MASK) + 1; -+ w->size = (u64)(size | ~DDR_SIZE_MASK) + 1; - } - } - mvebu_mbus_dram_info.num_cs = cs; -diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c -index 9a7e37cf56b0..e1d7373e63e0 100644 ---- a/drivers/clocksource/cs5535-clockevt.c -+++ b/drivers/clocksource/cs5535-clockevt.c -@@ -117,7 +117,8 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) - /* Turn off the clock (and clear the event) */ - disable_timer(cs5535_event_clock); - -- if (clockevent_state_shutdown(&cs5535_clockevent)) -+ if (clockevent_state_detached(&cs5535_clockevent) || -+ clockevent_state_shutdown(&cs5535_clockevent)) - return IRQ_HANDLED; - - /* Clear the counter */ -diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c -index 3ef01071f073..103471ff4dc4 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c -+++ b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c -@@ -40,5 +40,5 @@ int - g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine) - { - return nvkm_xtensa_new_(&g84_bsp, device, index, -- true, 0x103000, pengine); -+ device->chipset != 0x92, 0x103000, pengine); - } -diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c -index e04a2296ecd0..5bb7f7e0f11f 100644 ---- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c -+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c -@@ -240,6 +240,8 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) - mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); - } - -+ mmu->func->flush(vm); -+ - nvkm_memory_del(&pgt); - } - } -diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c -index 639d1a9c8793..1111cb966a44 100644 ---- a/drivers/i2c/busses/i2c-ismt.c -+++ b/drivers/i2c/busses/i2c-ismt.c -@@ -338,12 +338,15 @@ static int ismt_process_desc(const struct ismt_desc *desc, - data->word = dma_buffer[0] | (dma_buffer[1] << 8); - break; - case I2C_SMBUS_BLOCK_DATA: -- case I2C_SMBUS_I2C_BLOCK_DATA: - if (desc->rxbytes != dma_buffer[0] + 1) - return -EMSGSIZE; - - memcpy(data->block, dma_buffer, desc->rxbytes); - break; -+ case I2C_SMBUS_I2C_BLOCK_DATA: -+ memcpy(&data->block[1], dma_buffer, desc->rxbytes); -+ data->block[0] = desc->rxbytes; -+ break; - } - return 0; - } -diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c -index 113e64fcd73b..4c6707ecc619 100644 ---- a/drivers/net/can/usb/esd_usb2.c -+++ b/drivers/net/can/usb/esd_usb2.c -@@ -333,7 +333,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, - } - - cf->can_id = id & ESD_IDMASK; -- cf->can_dlc = get_can_dlc(msg->msg.rx.dlc); -+ cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR); - - if (id & ESD_EXTID) - cf->can_id |= CAN_EFF_FLAG; -diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c -index ae5709354546..27e2352fcc42 100644 ---- a/drivers/net/can/usb/gs_usb.c -+++ b/drivers/net/can/usb/gs_usb.c -@@ -356,6 +356,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) - - gs_free_tx_context(txc); - -+ atomic_dec(&dev->active_tx_urbs); -+ - netif_wake_queue(netdev); - } - -@@ -444,14 +446,6 @@ static void gs_usb_xmit_callback(struct urb *urb) - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); -- -- atomic_dec(&dev->active_tx_urbs); -- -- if (!netif_device_present(netdev)) -- return; -- -- if (netif_queue_stopped(netdev)) -- netif_wake_queue(netdev); - } - - static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct net_device *netdev) -diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c -index 99dac9b8a082..c75bfd3f8cb3 100644 ---- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c -@@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) - } - - static void --wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, -- u8 len) -+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events, -+ const u8 *dlys, u8 len) - { - u32 t1_offset, t2_offset; - u8 ctr; -@@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) - static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) - { - u16 currband; -- s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; -- s8 *lna1_gain_db = NULL; -- s8 *lna1_gain_db_2 = NULL; -- s8 *lna2_gain_db = NULL; -- s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; -- s8 *tia_gain_db; -- s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; -- s8 *tia_gainbits; -- u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; -- u16 *rfseq_init_gain; -+ static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; -+ const s8 *lna1_gain_db = NULL; -+ const s8 *lna1_gain_db_2 = NULL; -+ const s8 *lna2_gain_db = NULL; -+ static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; -+ const s8 *tia_gain_db; -+ static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; -+ const s8 *tia_gainbits; -+ static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; -+ const u16 *rfseq_init_gain; - u16 init_gaincode; - u16 clip1hi_gaincode; - u16 clip1md_gaincode = 0; -@@ -15310,10 +15310,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) - - if ((freq <= 5080) || (freq == 5825)) { - -- s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; -- s8 lna1A_gain_db_2_rev7[] = { -- 11, 17, 22, 25}; -- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; -+ static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; -+ static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25}; -+ static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; - - crsminu_th = 0x3e; - lna1_gain_db = lna1A_gain_db_rev7; -@@ -15321,10 +15320,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) - lna2_gain_db = lna2A_gain_db_rev7; - } else if ((freq >= 5500) && (freq <= 5700)) { - -- s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; -- s8 lna1A_gain_db_2_rev7[] = { -- 12, 18, 22, 26}; -- s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; -+ static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; -+ static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; -+ static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; - - crsminu_th = 0x45; - clip1md_gaincode_B = 0x14; -@@ -15335,10 +15333,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) - lna2_gain_db = lna2A_gain_db_rev7; - } else { - -- s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; -- s8 lna1A_gain_db_2_rev7[] = { -- 12, 18, 22, 26}; -- s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; -+ static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; -+ static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; -+ static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; - - crsminu_th = 0x41; - lna1_gain_db = lna1A_gain_db_rev7; -@@ -15450,65 +15447,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) - NPHY_RFSEQ_CMD_CLR_HIQ_DIS, - NPHY_RFSEQ_CMD_SET_HPF_BW - }; -- u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; -- s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; -- s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; -- s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; -- s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; -- s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; -- s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; -- s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; -- s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; -- s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; -- s8 *lna1_gain_db = NULL; -- s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; -- s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; -- s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; -- s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; -- s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; -- s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; -- s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; -- s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; -- s8 *lna2_gain_db = NULL; -- s8 tiaG_gain_db[] = { -+ static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; -+ static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; -+ static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; -+ static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; -+ static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; -+ static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; -+ static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; -+ static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; -+ static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; -+ static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; -+ const s8 *lna1_gain_db = NULL; -+ static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; -+ static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; -+ static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; -+ static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; -+ static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; -+ static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; -+ static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; -+ static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; -+ const s8 *lna2_gain_db = NULL; -+ static const s8 tiaG_gain_db[] = { - 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; -- s8 tiaA_gain_db[] = { -+ static const s8 tiaA_gain_db[] = { - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; -- s8 tiaA_gain_db_rev4[] = { -+ static const s8 tiaA_gain_db_rev4[] = { - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -- s8 tiaA_gain_db_rev5[] = { -+ static const s8 tiaA_gain_db_rev5[] = { - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -- s8 tiaA_gain_db_rev6[] = { -+ static const s8 tiaA_gain_db_rev6[] = { - 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; -- s8 *tia_gain_db; -- s8 tiaG_gainbits[] = { -+ const s8 *tia_gain_db; -+ static const s8 tiaG_gainbits[] = { - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; -- s8 tiaA_gainbits[] = { -+ static const s8 tiaA_gainbits[] = { - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; -- s8 tiaA_gainbits_rev4[] = { -+ static const s8 tiaA_gainbits_rev4[] = { - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -- s8 tiaA_gainbits_rev5[] = { -+ static const s8 tiaA_gainbits_rev5[] = { - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -- s8 tiaA_gainbits_rev6[] = { -+ static const s8 tiaA_gainbits_rev6[] = { - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; -- s8 *tia_gainbits; -- s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; -- s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; -- u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; -- u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; -- u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; -- u16 rfseqG_init_gain_rev5_elna[] = { -+ const s8 *tia_gainbits; -+ static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; -+ static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; -+ static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; -+ static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; -+ static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; -+ static const u16 rfseqG_init_gain_rev5_elna[] = { - 0x013f, 0x013f, 0x013f, 0x013f }; -- u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; -- u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; -- u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; -- u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; -- u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; -- u16 rfseqA_init_gain_rev4_elna[] = { -+ static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; -+ static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; -+ static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; -+ static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; -+ static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; -+ static const u16 rfseqA_init_gain_rev4_elna[] = { - 0x314f, 0x314f, 0x314f, 0x314f }; -- u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; -- u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; -- u16 *rfseq_init_gain; -+ static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; -+ static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; -+ const u16 *rfseq_init_gain; - u16 initG_gaincode = 0x627e; - u16 initG_gaincode_rev4 = 0x527e; - u16 initG_gaincode_rev5 = 0x427e; -@@ -15538,10 +15535,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) - u16 clip1mdA_gaincode_rev6 = 0x2084; - u16 clip1md_gaincode = 0; - u16 clip1loG_gaincode = 0x0074; -- u16 clip1loG_gaincode_rev5[] = { -+ static const u16 clip1loG_gaincode_rev5[] = { - 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c - }; -- u16 clip1loG_gaincode_rev6[] = { -+ static const u16 clip1loG_gaincode_rev6[] = { - 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e - }; - u16 clip1loG_gaincode_rev6_224B0 = 0x1074; -@@ -16066,7 +16063,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) - - static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - { -- u8 rfseq_rx2tx_events[] = { -+ static const u8 rfseq_rx2tx_events[] = { - NPHY_RFSEQ_CMD_NOP, - NPHY_RFSEQ_CMD_RXG_FBW, - NPHY_RFSEQ_CMD_TR_SWITCH, -@@ -16076,7 +16073,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - NPHY_RFSEQ_CMD_EXT_PA - }; - u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; -- u8 rfseq_tx2rx_events[] = { -+ static const u8 rfseq_tx2rx_events[] = { - NPHY_RFSEQ_CMD_NOP, - NPHY_RFSEQ_CMD_EXT_PA, - NPHY_RFSEQ_CMD_TX_GAIN, -@@ -16085,8 +16082,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - NPHY_RFSEQ_CMD_RXG_FBW, - NPHY_RFSEQ_CMD_CLR_HIQ_DIS - }; -- u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; -- u8 rfseq_tx2rx_events_rev3[] = { -+ static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; -+ static const u8 rfseq_tx2rx_events_rev3[] = { - NPHY_REV3_RFSEQ_CMD_EXT_PA, - NPHY_REV3_RFSEQ_CMD_INT_PA_PU, - NPHY_REV3_RFSEQ_CMD_TX_GAIN, -@@ -16096,7 +16093,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, - NPHY_REV3_RFSEQ_CMD_END - }; -- u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; -+ static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; - u8 rfseq_rx2tx_events_rev3[] = { - NPHY_REV3_RFSEQ_CMD_NOP, - NPHY_REV3_RFSEQ_CMD_RXG_FBW, -@@ -16110,7 +16107,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - }; - u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; - -- u8 rfseq_rx2tx_events_rev3_ipa[] = { -+ static const u8 rfseq_rx2tx_events_rev3_ipa[] = { - NPHY_REV3_RFSEQ_CMD_NOP, - NPHY_REV3_RFSEQ_CMD_RXG_FBW, - NPHY_REV3_RFSEQ_CMD_TR_SWITCH, -@@ -16121,15 +16118,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - NPHY_REV3_RFSEQ_CMD_INT_PA_PU, - NPHY_REV3_RFSEQ_CMD_END - }; -- u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; -- u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; -+ static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; -+ static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; - - s16 alpha0, alpha1, alpha2; - s16 beta0, beta1, beta2; - u32 leg_data_weights, ht_data_weights, nss1_data_weights, - stbc_data_weights; - u8 chan_freq_range = 0; -- u16 dac_control = 0x0002; -+ static const u16 dac_control = 0x0002; - u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; - u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; - u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; -@@ -16139,8 +16136,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; - u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; - u16 *aux_adc_gain; -- u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; -- u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; -+ static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; -+ static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; - s32 min_nvar_val = 0x18d; - s32 min_nvar_offset_6mbps = 20; - u8 pdetrange; -@@ -16151,9 +16148,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) - u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; - u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; - u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; -- u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; -- u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; -- u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; -+ static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; -+ static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; -+ static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; - u16 ipalvlshift_3p3_war_en = 0; - u16 rccal_bcap_val, rccal_scap_val; - u16 rccal_tx20_11b_bcap = 0; -@@ -24291,13 +24288,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) - u16 bbmult; - u16 tblentry; - -- struct nphy_txiqcal_ladder ladder_lo[] = { -+ static const struct nphy_txiqcal_ladder ladder_lo[] = { - {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, - {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, - {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} - }; - -- struct nphy_txiqcal_ladder ladder_iq[] = { -+ static const struct nphy_txiqcal_ladder ladder_iq[] = { - {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, - {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, - {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} -@@ -25773,67 +25770,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, - u16 cal_gain[2]; - struct nphy_iqcal_params cal_params[2]; - u32 tbl_len; -- void *tbl_ptr; -+ const void *tbl_ptr; - bool ladder_updated[2]; - u8 mphase_cal_lastphase = 0; - int bcmerror = 0; - bool phyhang_avoid_state = false; - -- u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { -+ static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { - 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, - 0x1902, - 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, - 0x6407 - }; - -- u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { -+ static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { - 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, - 0x3200, - 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, - 0x6407 - }; - -- u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { -+ static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { - 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, - 0x1202, - 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, - 0x4707 - }; - -- u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { -+ static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { - 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, - 0x2300, - 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, - 0x4707 - }; - -- u16 tbl_tx_iqlo_cal_startcoefs[] = { -+ static const u16 tbl_tx_iqlo_cal_startcoefs[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000 - }; - -- u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { -+ static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { - 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, - 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 - }; - -- u16 tbl_tx_iqlo_cal_cmds_recal[] = { -+ static const u16 tbl_tx_iqlo_cal_cmds_recal[] = { - 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, - 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 - }; - -- u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { -+ static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000 - }; - -- u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { -+ static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { - 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, - 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 - }; - -- u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { -+ static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { - 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, - 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 - }; -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -index c2103e7a8132..bbb789f8990b 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -@@ -1127,7 +1127,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) - } - if (0 == tmp) { - read_addr = REG_DBI_RDATA + addr % 4; -- ret = rtl_read_byte(rtlpriv, read_addr); -+ ret = rtl_read_word(rtlpriv, read_addr); - } - return ret; - } -diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c -index df96f5f88c15..3f6bb3fff890 100644 ---- a/drivers/usb/class/cdc-acm.c -+++ b/drivers/usb/class/cdc-acm.c -@@ -1762,6 +1762,9 @@ static const struct usb_device_id acm_ids[] = { - { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ - .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ - }, -+ { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ -+ .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */ -+ }, - - { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ - .driver_info = CLEAR_HALT_CONDITIONS, -diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c -index d9d048fc9082..5172bec612eb 100644 ---- a/drivers/usb/core/config.c -+++ b/drivers/usb/core/config.c -@@ -926,10 +926,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) - for (i = 0; i < num; i++) { - buffer += length; - cap = (struct usb_dev_cap_header *)buffer; -- length = cap->bLength; - -- if (total_len < length) -+ if (total_len < sizeof(*cap) || total_len < cap->bLength) { -+ dev->bos->desc->bNumDeviceCaps = i; - break; -+ } -+ length = cap->bLength; - total_len -= length; - - if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index bd9419213d06..873ba02d59e6 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -1417,11 +1417,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb - totlen += isopkt[u].length; - } - u *= sizeof(struct usb_iso_packet_descriptor); -- if (totlen <= uurb->buffer_length) -- uurb->buffer_length = totlen; -- else -- WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d", -- totlen, uurb->buffer_length); -+ uurb->buffer_length = totlen; - break; - - default: -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 51bba58c0c3b..22e61786354a 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -2656,13 +2656,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return -ENOTCONN; - -- /* bomb out completely if the connection bounced. A USB 3.0 -- * connection may bounce if multiple warm resets were issued, -+ /* Retry if connect change is set but status is still connected. -+ * A USB 3.0 connection may bounce if multiple warm resets were issued, - * but the device may have successfully re-connected. Ignore it. - */ - if (!hub_is_superspeed(hub->hdev) && -- (portchange & USB_PORT_STAT_C_CONNECTION)) -- return -ENOTCONN; -+ (portchange & USB_PORT_STAT_C_CONNECTION)) { -+ usb_clear_port_feature(hub->hdev, port1, -+ USB_PORT_FEAT_C_CONNECTION); -+ return -EAGAIN; -+ } - - if (!(portstatus & USB_PORT_STAT_ENABLE)) - return -EBUSY; -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index 82806e311202..a6aaf2f193a4 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -221,6 +221,10 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Corsair Strafe RGB */ - { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, - -+ /* MIDI keyboard WORLDE MINI */ -+ { USB_DEVICE(0x1c75, 0x0204), .driver_info = -+ USB_QUIRK_CONFIG_INTF_STRINGS }, -+ - /* Acer C120 LED Projector */ - { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, - -diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c -index 00eed5d66fda..06d83825923a 100644 ---- a/drivers/usb/musb/musb_core.c -+++ b/drivers/usb/musb/musb_core.c -@@ -877,7 +877,7 @@ b_host: - */ - if (int_usb & MUSB_INTR_RESET) { - handled = IRQ_HANDLED; -- if (devctl & MUSB_DEVCTL_HM) { -+ if (is_host_active(musb)) { - /* - * When BABBLE happens what we can depends on which - * platform MUSB is running, because some platforms -@@ -887,9 +887,7 @@ b_host: - * drop the session. - */ - dev_err(musb->controller, "Babble\n"); -- -- if (is_host_active(musb)) -- musb_recover_from_babble(musb); -+ musb_recover_from_babble(musb); - } else { - dev_dbg(musb->controller, "BUS RESET as %s\n", - usb_otg_state_string(musb->xceiv->otg->state)); -diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c -index d9b0dc461439..2d3be66fb563 100644 ---- a/drivers/usb/musb/sunxi.c -+++ b/drivers/usb/musb/sunxi.c -@@ -320,6 +320,8 @@ static int sunxi_musb_exit(struct musb *musb) - if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) - sunxi_sram_release(musb->controller->parent); - -+ devm_usb_put_phy(glue->dev, glue->xceiv); -+ - return 0; - } - -diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c -index 39e683096e94..45182c65fa1f 100644 ---- a/drivers/usb/serial/metro-usb.c -+++ b/drivers/usb/serial/metro-usb.c -@@ -45,6 +45,7 @@ struct metrousb_private { - static const struct usb_device_id id_table[] = { - { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, - { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x0c2e, 0x0730, 0xff) }, /* MS7820 */ - { }, /* Terminating entry. */ - }; - MODULE_DEVICE_TABLE(usb, id_table); -diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c -index 505f8afde57c..9a1bc638abce 100644 ---- a/fs/ext4/crypto_key.c -+++ b/fs/ext4/crypto_key.c -@@ -204,6 +204,12 @@ int ext4_get_encryption_info(struct inode *inode) - } - down_read(&keyring_key->sem); - ukp = user_key_payload(keyring_key); -+ if (!ukp) { -+ /* key was revoked before we acquired its semaphore */ -+ res = -EKEYREVOKED; -+ up_read(&keyring_key->sem); -+ goto out; -+ } - if (ukp->datalen != sizeof(struct ext4_encryption_key)) { - res = -EINVAL; - up_read(&keyring_key->sem); -diff --git a/fs/f2fs/crypto.c b/fs/f2fs/crypto.c -index 4a62ef14e932..d879c6c846b7 100644 ---- a/fs/f2fs/crypto.c -+++ b/fs/f2fs/crypto.c -@@ -362,7 +362,6 @@ static int f2fs_page_crypto(struct f2fs_crypto_ctx *ctx, - else - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { -- BUG_ON(req->base.data != &ecr); - wait_for_completion(&ecr.completion); - res = ecr.res; - } -diff --git a/fs/f2fs/crypto_fname.c b/fs/f2fs/crypto_fname.c -index 38349ed5ea51..0fce444dd5ae 100644 ---- a/fs/f2fs/crypto_fname.c -+++ b/fs/f2fs/crypto_fname.c -@@ -124,7 +124,6 @@ static int f2fs_fname_encrypt(struct inode *inode, - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { -- BUG_ON(req->base.data != &ecr); - wait_for_completion(&ecr.completion); - res = ecr.res; - } -@@ -180,7 +179,6 @@ static int f2fs_fname_decrypt(struct inode *inode, - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); - res = crypto_ablkcipher_decrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { -- BUG_ON(req->base.data != &ecr); - wait_for_completion(&ecr.completion); - res = ecr.res; - } -diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c -index 18595d7a0efc..7e62889a1d3d 100644 ---- a/fs/f2fs/crypto_key.c -+++ b/fs/f2fs/crypto_key.c -@@ -75,7 +75,6 @@ static int f2fs_derive_key_aes(char deriving_key[F2FS_AES_128_ECB_KEY_SIZE], - F2FS_AES_256_XTS_KEY_SIZE, NULL); - res = crypto_ablkcipher_encrypt(req); - if (res == -EINPROGRESS || res == -EBUSY) { -- BUG_ON(req->base.data != &ecr); - wait_for_completion(&ecr.completion); - res = ecr.res; - } -@@ -189,18 +188,38 @@ int f2fs_get_encryption_info(struct inode *inode) - keyring_key = NULL; - goto out; - } -- BUG_ON(keyring_key->type != &key_type_logon); -+ if (keyring_key->type != &key_type_logon) { -+ printk_once(KERN_WARNING "f2fs: key type must be logon\n"); -+ res = -ENOKEY; -+ goto out; -+ } -+ down_read(&keyring_key->sem); - ukp = user_key_payload(keyring_key); -+ if (!ukp) { -+ /* key was revoked before we acquired its semaphore */ -+ res = -EKEYREVOKED; -+ up_read(&keyring_key->sem); -+ goto out; -+ } - if (ukp->datalen != sizeof(struct f2fs_encryption_key)) { - res = -EINVAL; -+ up_read(&keyring_key->sem); - goto out; - } - master_key = (struct f2fs_encryption_key *)ukp->data; - BUILD_BUG_ON(F2FS_AES_128_ECB_KEY_SIZE != - F2FS_KEY_DERIVATION_NONCE_SIZE); -- BUG_ON(master_key->size != F2FS_AES_256_XTS_KEY_SIZE); -+ if (master_key->size != F2FS_AES_256_XTS_KEY_SIZE) { -+ printk_once(KERN_WARNING -+ "f2fs: key size incorrect: %d\n", -+ master_key->size); -+ res = -ENOKEY; -+ up_read(&keyring_key->sem); -+ goto out; -+ } - res = f2fs_derive_key_aes(ctx.nonce, master_key->raw, - raw_key); -+ up_read(&keyring_key->sem); - if (res) - goto out; - -diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c -index 4b449d263333..01eed94b01ea 100644 ---- a/fs/f2fs/file.c -+++ b/fs/f2fs/file.c -@@ -1541,12 +1541,18 @@ static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) - sizeof(policy))) - return -EFAULT; - -+ err = mnt_want_write_file(filp); -+ if (err) -+ return err; -+ - mutex_lock(&inode->i_mutex); - - err = f2fs_process_policy(&policy, inode); - - mutex_unlock(&inode->i_mutex); - -+ mnt_drop_write_file(filp); -+ - return err; - #else - return -EOPNOTSUPP; -diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c -index 6b028b7c4250..926580a85153 100644 ---- a/fs/fscache/object-list.c -+++ b/fs/fscache/object-list.c -@@ -330,6 +330,13 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) - rcu_read_lock(); - - confkey = user_key_payload(key); -+ if (!confkey) { -+ /* key was revoked */ -+ rcu_read_unlock(); -+ key_put(key); -+ goto no_config; -+ } -+ - buf = confkey->data; - - for (len = confkey->datalen - 1; len >= 0; len--) { -diff --git a/include/linux/key.h b/include/linux/key.h -index dcc115e8dd03..af071ca73079 100644 ---- a/include/linux/key.h -+++ b/include/linux/key.h -@@ -126,6 +126,11 @@ static inline bool is_key_possessed(const key_ref_t key_ref) - return (unsigned long) key_ref & 1UL; - } - -+enum key_state { -+ KEY_IS_UNINSTANTIATED, -+ KEY_IS_POSITIVE, /* Positively instantiated */ -+}; -+ - /*****************************************************************************/ - /* - * authentication token / access credential / keyring -@@ -157,6 +162,7 @@ struct key { - * - may not match RCU dereferenced payload - * - payload should contain own length - */ -+ short state; /* Key state (+) or rejection error (-) */ - - #ifdef KEY_DEBUGGING - unsigned magic; -@@ -165,19 +171,17 @@ struct key { - #endif - - unsigned long flags; /* status flags (change with bitops) */ --#define KEY_FLAG_INSTANTIATED 0 /* set if key has been instantiated */ --#define KEY_FLAG_DEAD 1 /* set if key type has been deleted */ --#define KEY_FLAG_REVOKED 2 /* set if key had been revoked */ --#define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ --#define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ --#define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ --#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ --#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ --#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ --#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ --#define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ --#define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ --#define KEY_FLAG_UID_KEYRING 12 /* set if key is a user or user session keyring */ -+#define KEY_FLAG_DEAD 0 /* set if key type has been deleted */ -+#define KEY_FLAG_REVOKED 1 /* set if key had been revoked */ -+#define KEY_FLAG_IN_QUOTA 2 /* set if key consumes quota */ -+#define KEY_FLAG_USER_CONSTRUCT 3 /* set if key is being constructed in userspace */ -+#define KEY_FLAG_ROOT_CAN_CLEAR 4 /* set if key can be cleared by root without permission */ -+#define KEY_FLAG_INVALIDATED 5 /* set if key has been invalidated */ -+#define KEY_FLAG_TRUSTED 6 /* set if key is trusted */ -+#define KEY_FLAG_TRUSTED_ONLY 7 /* set if keyring only accepts links to trusted keys */ -+#define KEY_FLAG_BUILTIN 8 /* set if key is builtin */ -+#define KEY_FLAG_ROOT_CAN_INVAL 9 /* set if key can be invalidated by root without permission */ -+#define KEY_FLAG_UID_KEYRING 10 /* set if key is a user or user session keyring */ - - /* the key type and key description string - * - the desc is used to match a key against search criteria -@@ -203,7 +207,6 @@ struct key { - struct list_head name_link; - struct assoc_array keys; - }; -- int reject_error; - }; - }; - -@@ -319,17 +322,27 @@ extern void key_set_timeout(struct key *, unsigned); - #define KEY_NEED_SETATTR 0x20 /* Require permission to change attributes */ - #define KEY_NEED_ALL 0x3f /* All the above permissions */ - -+static inline short key_read_state(const struct key *key) -+{ -+ /* Barrier versus mark_key_instantiated(). */ -+ return smp_load_acquire(&key->state); -+} -+ - /** -- * key_is_instantiated - Determine if a key has been positively instantiated -+ * key_is_positive - Determine if a key has been positively instantiated - * @key: The key to check. - * - * Return true if the specified key has been positively instantiated, false - * otherwise. - */ --static inline bool key_is_instantiated(const struct key *key) -+static inline bool key_is_positive(const struct key *key) -+{ -+ return key_read_state(key) == KEY_IS_POSITIVE; -+} -+ -+static inline bool key_is_negative(const struct key *key) - { -- return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && -- !test_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ return key_read_state(key) < 0; - } - - #define rcu_dereference_key(KEY) \ -diff --git a/include/linux/mbus.h b/include/linux/mbus.h -index 1f7bc630d225..71a5a56b0bba 100644 ---- a/include/linux/mbus.h -+++ b/include/linux/mbus.h -@@ -29,8 +29,8 @@ struct mbus_dram_target_info - struct mbus_dram_window { - u8 cs_index; - u8 mbus_attr; -- u32 base; -- u32 size; -+ u64 base; -+ u64 size; - } cs[4]; - }; - -diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c -index 750ed601ddf7..8620fd01b3d0 100644 ---- a/kernel/sched/auto_group.c -+++ b/kernel/sched/auto_group.c -@@ -111,14 +111,11 @@ bool task_wants_autogroup(struct task_struct *p, struct task_group *tg) - { - if (tg != &root_task_group) - return false; -- - /* -- * We can only assume the task group can't go away on us if -- * autogroup_move_group() can see us on ->thread_group list. -+ * If we race with autogroup_move_group() the caller can use the old -+ * value of signal->autogroup but in this case sched_move_task() will -+ * be called again before autogroup_kref_put(). - */ -- if (p->flags & PF_EXITING) -- return false; -- - return true; - } - -@@ -138,13 +135,17 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) - } - - p->signal->autogroup = autogroup_kref_get(ag); -- -- if (!READ_ONCE(sysctl_sched_autogroup_enabled)) -- goto out; -- -+ /* -+ * We can't avoid sched_move_task() after we changed signal->autogroup, -+ * this process can already run with task_group() == prev->tg or we can -+ * race with cgroup code which can read autogroup = prev under rq->lock. -+ * In the latter case for_each_thread() can not miss a migrating thread, -+ * cpu_cgroup_attach() must not be possible after cgroup_exit() and it -+ * can't be removed from thread list, we hold ->siglock. -+ */ - for_each_thread(p, t) - sched_move_task(t); --out: -+ - unlock_task_sighand(p, &flags); - autogroup_kref_put(prev); - } -diff --git a/lib/digsig.c b/lib/digsig.c -index 07be6c1ef4e2..00c5c8179393 100644 ---- a/lib/digsig.c -+++ b/lib/digsig.c -@@ -87,6 +87,12 @@ static int digsig_verify_rsa(struct key *key, - down_read(&key->sem); - ukp = user_key_payload(key); - -+ if (!ukp) { -+ /* key was revoked before we acquired its semaphore */ -+ err = -EKEYREVOKED; -+ goto err1; -+ } -+ - if (ukp->datalen < sizeof(*pkh)) - goto err1; - -diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index c79b85eb4d4c..6abc5012200b 100644 ---- a/net/dns_resolver/dns_key.c -+++ b/net/dns_resolver/dns_key.c -@@ -224,7 +224,7 @@ static int dns_resolver_match_preparse(struct key_match_data *match_data) - static void dns_resolver_describe(const struct key *key, struct seq_file *m) - { - seq_puts(m, key->description); -- if (key_is_instantiated(key)) { -+ if (key_is_positive(key)) { - int err = PTR_ERR(key->payload.data[dns_key_error]); - - if (err) -diff --git a/security/keys/big_key.c b/security/keys/big_key.c -index 907c1522ee46..08c4cc5c2973 100644 ---- a/security/keys/big_key.c -+++ b/security/keys/big_key.c -@@ -138,7 +138,7 @@ void big_key_revoke(struct key *key) - - /* clear the quota */ - key_payload_reserve(key, 0); -- if (key_is_instantiated(key) && -+ if (key_is_positive(key) && - (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD) - vfs_truncate(path, 0); - } -@@ -170,7 +170,7 @@ void big_key_describe(const struct key *key, struct seq_file *m) - - seq_puts(m, key->description); - -- if (key_is_instantiated(key)) -+ if (key_is_positive(key)) - seq_printf(m, ": %zu [%s]", - datalen, - datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); -diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c -index 31898856682e..ce295c0c1da0 100644 ---- a/security/keys/encrypted-keys/encrypted.c -+++ b/security/keys/encrypted-keys/encrypted.c -@@ -315,6 +315,13 @@ static struct key *request_user_key(const char *master_desc, const u8 **master_k - - down_read(&ukey->sem); - upayload = user_key_payload(ukey); -+ if (!upayload) { -+ /* key was revoked before we acquired its semaphore */ -+ up_read(&ukey->sem); -+ key_put(ukey); -+ ukey = ERR_PTR(-EKEYREVOKED); -+ goto error; -+ } - *master_key = upayload->data; - *master_keylen = upayload->datalen; - error: -@@ -845,7 +852,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) - size_t datalen = prep->datalen; - int ret = 0; - -- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) -+ if (key_is_negative(key)) - return -ENOKEY; - if (datalen <= 0 || datalen > 32767 || !prep->data) - return -EINVAL; -diff --git a/security/keys/gc.c b/security/keys/gc.c -index 9cb4fe4478a1..1659094d684d 100644 ---- a/security/keys/gc.c -+++ b/security/keys/gc.c -@@ -129,15 +129,15 @@ static noinline void key_gc_unused_keys(struct list_head *keys) - while (!list_empty(keys)) { - struct key *key = - list_entry(keys->next, struct key, graveyard_link); -+ short state = key->state; -+ - list_del(&key->graveyard_link); - - kdebug("- %u", key->serial); - key_check(key); - - /* Throw away the key data if the key is instantiated */ -- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && -- !test_bit(KEY_FLAG_NEGATIVE, &key->flags) && -- key->type->destroy) -+ if (state == KEY_IS_POSITIVE && key->type->destroy) - key->type->destroy(key); - - security_key_free(key); -@@ -151,7 +151,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys) - } - - atomic_dec(&key->user->nkeys); -- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) -+ if (state != KEY_IS_UNINSTANTIATED) - atomic_dec(&key->user->nikeys); - - key_user_put(key->user); -diff --git a/security/keys/key.c b/security/keys/key.c -index 51d23c623424..4d971bf88ac3 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -395,6 +395,18 @@ int key_payload_reserve(struct key *key, size_t datalen) - } - EXPORT_SYMBOL(key_payload_reserve); - -+/* -+ * Change the key state to being instantiated. -+ */ -+static void mark_key_instantiated(struct key *key, int reject_error) -+{ -+ /* Commit the payload before setting the state; barrier versus -+ * key_read_state(). -+ */ -+ smp_store_release(&key->state, -+ (reject_error < 0) ? reject_error : KEY_IS_POSITIVE); -+} -+ - /* - * Instantiate a key and link it into the target keyring atomically. Must be - * called with the target keyring's semaphore writelocked. The target key's -@@ -418,14 +430,14 @@ static int __key_instantiate_and_link(struct key *key, - mutex_lock(&key_construction_mutex); - - /* can't instantiate twice */ -- if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { -+ if (key->state == KEY_IS_UNINSTANTIATED) { - /* instantiate the key */ - ret = key->type->instantiate(key, prep); - - if (ret == 0) { - /* mark the key as being instantiated */ - atomic_inc(&key->user->nikeys); -- set_bit(KEY_FLAG_INSTANTIATED, &key->flags); -+ mark_key_instantiated(key, 0); - - if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) - awaken = 1; -@@ -553,13 +565,10 @@ int key_reject_and_link(struct key *key, - mutex_lock(&key_construction_mutex); - - /* can't instantiate twice */ -- if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { -+ if (key->state == KEY_IS_UNINSTANTIATED) { - /* mark the key as being negatively instantiated */ - atomic_inc(&key->user->nikeys); -- key->reject_error = -error; -- smp_wmb(); -- set_bit(KEY_FLAG_NEGATIVE, &key->flags); -- set_bit(KEY_FLAG_INSTANTIATED, &key->flags); -+ mark_key_instantiated(key, -error); - now = current_kernel_time(); - key->expiry = now.tv_sec + timeout; - key_schedule_gc(key->expiry + key_gc_delay); -@@ -731,8 +740,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref, - - ret = key->type->update(key, prep); - if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ /* Updating a negative key positively instantiates it */ -+ mark_key_instantiated(key, 0); - - up_write(&key->sem); - -@@ -907,6 +916,16 @@ error: - */ - __key_link_end(keyring, &index_key, edit); - -+ key = key_ref_to_ptr(key_ref); -+ if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) { -+ ret = wait_for_key_construction(key, true); -+ if (ret < 0) { -+ key_ref_put(key_ref); -+ key_ref = ERR_PTR(ret); -+ goto error_free_prep; -+ } -+ } -+ - key_ref = __key_update(key_ref, &prep); - goto error_free_prep; - } -@@ -957,8 +976,8 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) - - ret = key->type->update(key, &prep); - if (ret == 0) -- /* updating a negative key instantiates it */ -- clear_bit(KEY_FLAG_NEGATIVE, &key->flags); -+ /* Updating a negative key positively instantiates it */ -+ mark_key_instantiated(key, 0); - - up_write(&key->sem); - -diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c -index a009dc66eb8f..2e741e1a8712 100644 ---- a/security/keys/keyctl.c -+++ b/security/keys/keyctl.c -@@ -738,10 +738,9 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) - - key = key_ref_to_ptr(key_ref); - -- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { -- ret = -ENOKEY; -- goto error2; -- } -+ ret = key_read_state(key); -+ if (ret < 0) -+ goto error2; /* Negatively instantiated */ - - /* see if we can read it directly */ - ret = key_permission(key_ref, KEY_NEED_READ); -@@ -873,7 +872,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) - atomic_dec(&key->user->nkeys); - atomic_inc(&newowner->nkeys); - -- if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { -+ if (key->state != KEY_IS_UNINSTANTIATED) { - atomic_dec(&key->user->nikeys); - atomic_inc(&newowner->nikeys); - } -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index 0c8dd4fbe130..ef828238cdc0 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -407,7 +407,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) - else - seq_puts(m, "[anon]"); - -- if (key_is_instantiated(keyring)) { -+ if (key_is_positive(keyring)) { - if (keyring->keys.nr_leaves_on_tree != 0) - seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree); - else -@@ -522,7 +522,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data) - { - struct keyring_search_context *ctx = iterator_data; - const struct key *key = keyring_ptr_to_key(object); -- unsigned long kflags = key->flags; -+ unsigned long kflags = READ_ONCE(key->flags); -+ short state = READ_ONCE(key->state); - - kenter("{%d}", key->serial); - -@@ -566,9 +567,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data) - - if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { - /* we set a different error code if we pass a negative key */ -- if (kflags & (1 << KEY_FLAG_NEGATIVE)) { -- smp_rmb(); -- ctx->result = ERR_PTR(key->reject_error); -+ if (state < 0) { -+ ctx->result = ERR_PTR(state); - kleave(" = %d [neg]", ctx->skipped_ret); - goto skipped; - } -diff --git a/security/keys/proc.c b/security/keys/proc.c -index b9f531c9e4fa..036128682463 100644 ---- a/security/keys/proc.c -+++ b/security/keys/proc.c -@@ -182,6 +182,7 @@ static int proc_keys_show(struct seq_file *m, void *v) - unsigned long timo; - key_ref_t key_ref, skey_ref; - char xbuf[16]; -+ short state; - int rc; - - struct keyring_search_context ctx = { -@@ -240,17 +241,19 @@ static int proc_keys_show(struct seq_file *m, void *v) - sprintf(xbuf, "%luw", timo / (60*60*24*7)); - } - -+ state = key_read_state(key); -+ - #define showflag(KEY, LETTER, FLAG) \ - (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') - - seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", - key->serial, -- showflag(key, 'I', KEY_FLAG_INSTANTIATED), -+ state != KEY_IS_UNINSTANTIATED ? 'I' : '-', - showflag(key, 'R', KEY_FLAG_REVOKED), - showflag(key, 'D', KEY_FLAG_DEAD), - showflag(key, 'Q', KEY_FLAG_IN_QUOTA), - showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), -- showflag(key, 'N', KEY_FLAG_NEGATIVE), -+ state < 0 ? 'N' : '-', - showflag(key, 'i', KEY_FLAG_INVALIDATED), - atomic_read(&key->usage), - xbuf, -diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c -index 7dd050f24261..ac1d5b2b1626 100644 ---- a/security/keys/process_keys.c -+++ b/security/keys/process_keys.c -@@ -727,7 +727,7 @@ try_again: - - ret = -EIO; - if (!(lflags & KEY_LOOKUP_PARTIAL) && -- !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) -+ key_read_state(key) == KEY_IS_UNINSTANTIATED) - goto invalid_key; - - /* check the permissions */ -diff --git a/security/keys/request_key.c b/security/keys/request_key.c -index c7a117c9a8f3..2ce733342b5a 100644 ---- a/security/keys/request_key.c -+++ b/security/keys/request_key.c -@@ -594,10 +594,9 @@ int wait_for_key_construction(struct key *key, bool intr) - intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); - if (ret) - return -ERESTARTSYS; -- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { -- smp_rmb(); -- return key->reject_error; -- } -+ ret = key_read_state(key); -+ if (ret < 0) -+ return ret; - return key_validate(key); - } - EXPORT_SYMBOL(wait_for_key_construction); -diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c -index 4f0f112fe276..217775fcd0f3 100644 ---- a/security/keys/request_key_auth.c -+++ b/security/keys/request_key_auth.c -@@ -73,7 +73,7 @@ static void request_key_auth_describe(const struct key *key, - - seq_puts(m, "key:"); - seq_puts(m, key->description); -- if (key_is_instantiated(key)) -+ if (key_is_positive(key)) - seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); - } - -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 16dec53184b6..509aedcf8310 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -1014,7 +1014,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - char *datablob; - int ret = 0; - -- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) -+ if (key_is_negative(key)) - return -ENOKEY; - p = key->payload.data[0]; - if (!p->migratable) -diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c -index 8705d79b2c6f..eba8a516ee9e 100644 ---- a/security/keys/user_defined.c -+++ b/security/keys/user_defined.c -@@ -120,7 +120,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) - - if (ret == 0) { - /* attach the new data, displacing the old */ -- if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) -+ if (key_is_positive(key)) - zap = key->payload.data[0]; - else - zap = NULL; -@@ -174,7 +174,7 @@ EXPORT_SYMBOL_GPL(user_destroy); - void user_describe(const struct key *key, struct seq_file *m) - { - seq_puts(m, key->description); -- if (key_is_instantiated(key)) -+ if (key_is_positive(key)) - seq_printf(m, ": %u", key->datalen); - } - -diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c -index 12ba83367b1b..ba5752ee9af3 100644 ---- a/sound/core/seq/seq_lock.c -+++ b/sound/core/seq/seq_lock.c -@@ -23,8 +23,6 @@ - #include - #include "seq_lock.h" - --#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) -- - /* wait until all locks are released */ - void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) - { -@@ -42,5 +40,3 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) - } - - EXPORT_SYMBOL(snd_use_lock_sync_helper); -- --#endif -diff --git a/sound/core/seq/seq_lock.h b/sound/core/seq/seq_lock.h -index 54044bc2c9ef..ac38031c370e 100644 ---- a/sound/core/seq/seq_lock.h -+++ b/sound/core/seq/seq_lock.h -@@ -3,8 +3,6 @@ - - #include - --#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) -- - typedef atomic_t snd_use_lock_t; - - /* initialize lock */ -@@ -20,14 +18,4 @@ typedef atomic_t snd_use_lock_t; - void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line); - #define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__) - --#else /* SMP || CONFIG_SND_DEBUG */ -- --typedef spinlock_t snd_use_lock_t; /* dummy */ --#define snd_use_lock_init(lockp) /**/ --#define snd_use_lock_use(lockp) /**/ --#define snd_use_lock_free(lockp) /**/ --#define snd_use_lock_sync(lockp) /**/ -- --#endif /* SMP || CONFIG_SND_DEBUG */ -- - #endif /* __SND_SEQ_LOCK_H */ -diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c -index 83741887faa1..3324f98c35f6 100644 ---- a/sound/pci/hda/hda_codec.c -+++ b/sound/pci/hda/hda_codec.c -@@ -1755,7 +1755,7 @@ static int get_kctl_0dB_offset(struct hda_codec *codec, - return -1; - if (*step_to_check && *step_to_check != step) { - codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n", --- *step_to_check, step); -+ *step_to_check, step); - return -1; - } - *step_to_check = step; -diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c -index 1cc20d138dae..9c5368e7ee23 100644 ---- a/sound/usb/quirks.c -+++ b/sound/usb/quirks.c -@@ -1305,6 +1305,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, - case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */ - case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */ - case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */ -+ case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */ - if (fp->altsetting == 2) - return SNDRV_PCM_FMTBIT_DSD_U32_BE; - break; diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.95-96.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.95-96.patch deleted file mode 100644 index 51487e92d..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.95-96.patch +++ /dev/null @@ -1,809 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt -deleted file mode 100644 -index 6ec1a880ac18..000000000000 ---- a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt -+++ /dev/null -@@ -1,46 +0,0 @@ --THS8135 Video DAC ------------------- -- --This is the binding for Texas Instruments THS8135 Video DAC bridge. -- --Required properties: -- --- compatible: Must be "ti,ths8135" -- --Required nodes: -- --This device has two video ports. Their connections are modelled using the OF --graph bindings specified in Documentation/devicetree/bindings/graph.txt. -- --- Video port 0 for RGB input --- Video port 1 for VGA output -- --Example --------- -- --vga-bridge { -- compatible = "ti,ths8135"; -- #address-cells = <1>; -- #size-cells = <0>; -- -- ports { -- #address-cells = <1>; -- #size-cells = <0>; -- -- port@0 { -- reg = <0>; -- -- vga_bridge_in: endpoint { -- remote-endpoint = <&lcdc_out_vga>; -- }; -- }; -- -- port@1 { -- reg = <1>; -- -- vga_bridge_out: endpoint { -- remote-endpoint = <&vga_con_in>; -- }; -- }; -- }; --}; -diff --git a/Makefile b/Makefile -index 57e1ea2a189a..12dfe1dcbaca 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 95 -+SUBLEVEL = 96 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c -index ac8975a65280..abf581ade8d2 100644 ---- a/arch/x86/kernel/cpu/microcode/intel.c -+++ b/arch/x86/kernel/cpu/microcode/intel.c -@@ -990,6 +990,18 @@ static int get_ucode_fw(void *to, const void *from, size_t n) - return 0; - } - -+static bool is_blacklisted(unsigned int cpu) -+{ -+ struct cpuinfo_x86 *c = &cpu_data(cpu); -+ -+ if (c->x86 == 6 && c->x86_model == 79) { -+ pr_err_once("late loading on model 79 is disabled.\n"); -+ return true; -+ } -+ -+ return false; -+} -+ - static enum ucode_state request_microcode_fw(int cpu, struct device *device, - bool refresh_fw) - { -@@ -998,6 +1010,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device, - const struct firmware *firmware; - enum ucode_state ret; - -+ if (is_blacklisted(cpu)) -+ return UCODE_NFOUND; -+ - sprintf(name, "intel-ucode/%02x-%02x-%02x", - c->x86, c->x86_model, c->x86_mask); - -@@ -1022,6 +1037,9 @@ static int get_ucode_user(void *to, const void *from, size_t n) - static enum ucode_state - request_microcode_user(int cpu, const void __user *buf, size_t size) - { -+ if (is_blacklisted(cpu)) -+ return UCODE_NFOUND; -+ - return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); - } - -diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c -index 681dce15fbc8..b8c50d883b2c 100644 ---- a/drivers/input/mouse/elan_i2c_core.c -+++ b/drivers/input/mouse/elan_i2c_core.c -@@ -1240,6 +1240,7 @@ static const struct acpi_device_id elan_acpi_id[] = { - { "ELAN0605", 0 }, - { "ELAN0609", 0 }, - { "ELAN060B", 0 }, -+ { "ELAN0611", 0 }, - { "ELAN1000", 0 }, - { } - }; -diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c -index 7c18249d6c8e..8b68a210277b 100644 ---- a/drivers/input/tablet/gtco.c -+++ b/drivers/input/tablet/gtco.c -@@ -231,13 +231,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, - - /* Walk this report and pull out the info we need */ - while (i < length) { -- prefix = report[i]; -- -- /* Skip over prefix */ -- i++; -+ prefix = report[i++]; - - /* Determine data size and save the data in the proper variable */ -- size = PREF_SIZE(prefix); -+ size = (1U << PREF_SIZE(prefix)) >> 1; -+ if (i + size > length) { -+ dev_err(ddev, -+ "Not enough data (need %d, have %d)\n", -+ i + size, length); -+ break; -+ } -+ - switch (size) { - case 1: - data = report[i]; -@@ -245,8 +249,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, - case 2: - data16 = get_unaligned_le16(&report[i]); - break; -- case 3: -- size = 4; -+ case 4: - data32 = get_unaligned_le32(&report[i]); - break; - } -diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c -index 68ef0a4cd821..b0c80859f746 100644 ---- a/drivers/net/can/sun4i_can.c -+++ b/drivers/net/can/sun4i_can.c -@@ -342,7 +342,7 @@ static int sun4i_can_start(struct net_device *dev) - - /* enter the selected mode */ - mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); -- if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) -+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) - mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE; - else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) - mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE; -@@ -811,7 +811,6 @@ static int sun4ican_probe(struct platform_device *pdev) - priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | - CAN_CTRLMODE_LISTENONLY | - CAN_CTRLMODE_LOOPBACK | -- CAN_CTRLMODE_PRESUME_ACK | - CAN_CTRLMODE_3_SAMPLES; - priv->base = addr; - priv->clk = clk; -diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c -index 022bfa13ebfa..c2e2821a3346 100644 ---- a/drivers/net/can/usb/kvaser_usb.c -+++ b/drivers/net/can/usb/kvaser_usb.c -@@ -134,6 +134,7 @@ static inline bool kvaser_is_usbcan(const struct usb_device_id *id) - #define CMD_RESET_ERROR_COUNTER 49 - #define CMD_TX_ACKNOWLEDGE 50 - #define CMD_CAN_ERROR_EVENT 51 -+#define CMD_FLUSH_QUEUE_REPLY 68 - - #define CMD_LEAF_USB_THROTTLE 77 - #define CMD_LEAF_LOG_MESSAGE 106 -@@ -1297,6 +1298,11 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev, - goto warn; - break; - -+ case CMD_FLUSH_QUEUE_REPLY: -+ if (dev->family != KVASER_LEAF) -+ goto warn; -+ break; -+ - default: - warn: dev_warn(dev->udev->dev.parent, - "Unhandled message (%d)\n", msg->id); -@@ -1607,7 +1613,8 @@ static int kvaser_usb_close(struct net_device *netdev) - if (err) - netdev_warn(netdev, "Cannot flush queue, error %d\n", err); - -- if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel)) -+ err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel); -+ if (err) - netdev_warn(netdev, "Cannot reset card, error %d\n", err); - - err = kvaser_usb_stop_chip(priv); -diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c -index 4940e8287df6..c3107358b3fb 100644 ---- a/drivers/regulator/fan53555.c -+++ b/drivers/regulator/fan53555.c -@@ -434,7 +434,10 @@ static const struct i2c_device_id fan53555_id[] = { - .name = "fan53555", - .driver_data = FAN53555_VENDOR_FAIRCHILD - }, { -- .name = "syr82x", -+ .name = "syr827", -+ .driver_data = FAN53555_VENDOR_SILERGY -+ }, { -+ .name = "syr828", - .driver_data = FAN53555_VENDOR_SILERGY - }, - { }, -diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c -index c00ac4650dce..38c8e308d4c8 100644 ---- a/drivers/s390/scsi/zfcp_aux.c -+++ b/drivers/s390/scsi/zfcp_aux.c -@@ -358,6 +358,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) - - adapter->next_port_scan = jiffies; - -+ adapter->erp_action.adapter = adapter; -+ - if (zfcp_qdio_setup(adapter)) - goto failed; - -@@ -514,6 +516,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, - port->dev.groups = zfcp_port_attr_groups; - port->dev.release = zfcp_port_release; - -+ port->erp_action.adapter = adapter; -+ port->erp_action.port = port; -+ - if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { - kfree(port); - goto err_out; -diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c -index 7ccfce559034..3b23d6754598 100644 ---- a/drivers/s390/scsi/zfcp_erp.c -+++ b/drivers/s390/scsi/zfcp_erp.c -@@ -193,9 +193,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, - atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, - &zfcp_sdev->status); - erp_action = &zfcp_sdev->erp_action; -- memset(erp_action, 0, sizeof(struct zfcp_erp_action)); -- erp_action->port = port; -- erp_action->sdev = sdev; -+ WARN_ON_ONCE(erp_action->port != port); -+ WARN_ON_ONCE(erp_action->sdev != sdev); - if (!(atomic_read(&zfcp_sdev->status) & - ZFCP_STATUS_COMMON_RUNNING)) - act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; -@@ -208,8 +207,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, - zfcp_erp_action_dismiss_port(port); - atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); - erp_action = &port->erp_action; -- memset(erp_action, 0, sizeof(struct zfcp_erp_action)); -- erp_action->port = port; -+ WARN_ON_ONCE(erp_action->port != port); -+ WARN_ON_ONCE(erp_action->sdev != NULL); - if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) - act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; - break; -@@ -219,7 +218,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, - zfcp_erp_action_dismiss_adapter(adapter); - atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); - erp_action = &adapter->erp_action; -- memset(erp_action, 0, sizeof(struct zfcp_erp_action)); -+ WARN_ON_ONCE(erp_action->port != NULL); -+ WARN_ON_ONCE(erp_action->sdev != NULL); - if (!(atomic_read(&adapter->status) & - ZFCP_STATUS_COMMON_RUNNING)) - act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; -@@ -229,7 +229,11 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, - return NULL; - } - -- erp_action->adapter = adapter; -+ WARN_ON_ONCE(erp_action->adapter != adapter); -+ memset(&erp_action->list, 0, sizeof(erp_action->list)); -+ memset(&erp_action->timer, 0, sizeof(erp_action->timer)); -+ erp_action->step = ZFCP_ERP_STEP_UNINITIALIZED; -+ erp_action->fsf_req_id = 0; - erp_action->action = need; - erp_action->status = act_status; - -diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c -index 9bd9b9a29dfc..a9b8104b982e 100644 ---- a/drivers/s390/scsi/zfcp_scsi.c -+++ b/drivers/s390/scsi/zfcp_scsi.c -@@ -115,10 +115,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) - struct zfcp_unit *unit; - int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE; - -+ zfcp_sdev->erp_action.adapter = adapter; -+ zfcp_sdev->erp_action.sdev = sdev; -+ - port = zfcp_get_port_by_wwpn(adapter, rport->port_name); - if (!port) - return -ENXIO; - -+ zfcp_sdev->erp_action.port = port; -+ - unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); - if (unit) - put_device(&unit->dev); -diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c -index 39e8b5dc23fa..38f77e127349 100644 ---- a/drivers/scsi/sg.c -+++ b/drivers/scsi/sg.c -@@ -848,7 +848,7 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo) - - val = 0; - list_for_each_entry(srp, &sfp->rq_list, entry) { -- if (val > SG_MAX_QUEUE) -+ if (val >= SG_MAX_QUEUE) - break; - rinfo[val].req_state = srp->done + 1; - rinfo[val].problem = -diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c -index a8a2d5005e6e..9df00101bfe1 100644 ---- a/drivers/usb/host/xhci-hub.c -+++ b/drivers/usb/host/xhci-hub.c -@@ -394,15 +394,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) - GFP_NOWAIT); - if (!command) { - spin_unlock_irqrestore(&xhci->lock, flags); -- xhci_free_command(xhci, cmd); -- return -ENOMEM; -+ ret = -ENOMEM; -+ goto cmd_cleanup; -+ } - -+ ret = xhci_queue_stop_endpoint(xhci, command, slot_id, -+ i, suspend); -+ if (ret) { -+ spin_unlock_irqrestore(&xhci->lock, flags); -+ xhci_free_command(xhci, command); -+ goto cmd_cleanup; - } -- xhci_queue_stop_endpoint(xhci, command, slot_id, i, -- suspend); - } - } -- xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); -+ ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); -+ if (ret) { -+ spin_unlock_irqrestore(&xhci->lock, flags); -+ goto cmd_cleanup; -+ } -+ - xhci_ring_cmd_db(xhci); - spin_unlock_irqrestore(&xhci->lock, flags); - -@@ -413,6 +423,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) - xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); - ret = -ETIME; - } -+ -+cmd_cleanup: - xhci_free_command(xhci, cmd); - return ret; - } -diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c -index 308600adf6e0..a4d749665c9f 100644 ---- a/drivers/xen/gntdev.c -+++ b/drivers/xen/gntdev.c -@@ -827,6 +827,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) - mutex_unlock(&priv->lock); - - if (use_ptemod) { -+ map->pages_vm_start = vma->vm_start; - err = apply_to_page_range(vma->vm_mm, vma->vm_start, - vma->vm_end - vma->vm_start, - find_grant_ptes, map); -@@ -864,7 +865,6 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) - set_grant_ptes_as_special, NULL); - } - #endif -- map->pages_vm_start = vma->vm_start; - } - - return 0; -diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c -index c69e1253b47b..0e3de1bb6500 100644 ---- a/fs/ceph/caps.c -+++ b/fs/ceph/caps.c -@@ -1850,6 +1850,7 @@ static int try_flush_caps(struct inode *inode, u64 *ptid) - retry: - spin_lock(&ci->i_ceph_lock); - if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { -+ spin_unlock(&ci->i_ceph_lock); - dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); - goto out; - } -@@ -1867,8 +1868,10 @@ retry: - mutex_lock(&session->s_mutex); - goto retry; - } -- if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) -+ if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) { -+ spin_unlock(&ci->i_ceph_lock); - goto out; -+ } - - flushing = __mark_caps_flushing(inode, session, &flush_tid, - &oldest_flush_tid); -diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h -index 7b39260c7bba..eae9cdb8af46 100644 ---- a/fs/ecryptfs/ecryptfs_kernel.h -+++ b/fs/ecryptfs/ecryptfs_kernel.h -@@ -84,11 +84,16 @@ struct ecryptfs_page_crypt_context { - static inline struct ecryptfs_auth_tok * - ecryptfs_get_encrypted_key_payload_data(struct key *key) - { -- if (key->type == &key_type_encrypted) -- return (struct ecryptfs_auth_tok *) -- (&((struct encrypted_key_payload *)key->payload.data[0])->payload_data); -- else -+ struct encrypted_key_payload *payload; -+ -+ if (key->type != &key_type_encrypted) - return NULL; -+ -+ payload = key->payload.data[0]; -+ if (!payload) -+ return ERR_PTR(-EKEYREVOKED); -+ -+ return (struct ecryptfs_auth_tok *)payload->payload_data; - } - - static inline struct key *ecryptfs_get_encrypted_key(char *sig) -@@ -114,12 +119,17 @@ static inline struct ecryptfs_auth_tok * - ecryptfs_get_key_payload_data(struct key *key) - { - struct ecryptfs_auth_tok *auth_tok; -+ const struct user_key_payload *ukp; - - auth_tok = ecryptfs_get_encrypted_key_payload_data(key); -- if (!auth_tok) -- return (struct ecryptfs_auth_tok *)user_key_payload(key)->data; -- else -+ if (auth_tok) - return auth_tok; -+ -+ ukp = user_key_payload(key); -+ if (!ukp) -+ return ERR_PTR(-EKEYREVOKED); -+ -+ return (struct ecryptfs_auth_tok *)ukp->data; - } - - #define ECRYPTFS_MAX_KEYSET_SIZE 1024 -diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c -index 6bd67e2011f0..20632ee51ae5 100644 ---- a/fs/ecryptfs/keystore.c -+++ b/fs/ecryptfs/keystore.c -@@ -458,7 +458,8 @@ out: - * @auth_tok_key: key containing the authentication token - * @auth_tok: authentication token - * -- * Returns zero on valid auth tok; -EINVAL otherwise -+ * Returns zero on valid auth tok; -EINVAL if the payload is invalid; or -+ * -EKEYREVOKED if the key was revoked before we acquired its semaphore. - */ - static int - ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, -@@ -467,6 +468,12 @@ ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, - int rc = 0; - - (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); -+ if (IS_ERR(*auth_tok)) { -+ rc = PTR_ERR(*auth_tok); -+ *auth_tok = NULL; -+ goto out; -+ } -+ - if (ecryptfs_verify_version((*auth_tok)->version)) { - printk(KERN_ERR "Data structure version mismatch. Userspace " - "tools must match eCryptfs kernel module with major " -diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c -index 4b5f2c4e69c8..5068dbf80ff8 100644 ---- a/fs/fuse/dir.c -+++ b/fs/fuse/dir.c -@@ -1295,7 +1295,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, - */ - over = !dir_emit(ctx, dirent->name, dirent->namelen, - dirent->ino, dirent->type); -- ctx->pos = dirent->off; -+ if (!over) -+ ctx->pos = dirent->off; - } - - buf += reclen; -diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h -index dd5f21e75805..856de39d0b89 100644 ---- a/include/uapi/linux/spi/spidev.h -+++ b/include/uapi/linux/spi/spidev.h -@@ -23,6 +23,7 @@ - #define SPIDEV_H - - #include -+#include - - /* User space versions of kernel symbols for SPI clocking modes, - * matching -diff --git a/kernel/workqueue.c b/kernel/workqueue.c -index 23231237f2e2..95cc76785a12 100644 ---- a/kernel/workqueue.c -+++ b/kernel/workqueue.c -@@ -68,6 +68,7 @@ enum { - * attach_mutex to avoid changing binding state while - * worker_attach_to_pool() is in progress. - */ -+ POOL_MANAGER_ACTIVE = 1 << 0, /* being managed */ - POOL_DISASSOCIATED = 1 << 2, /* cpu can't serve workers */ - - /* worker flags */ -@@ -163,7 +164,6 @@ struct worker_pool { - /* L: hash of busy workers */ - - /* see manage_workers() for details on the two manager mutexes */ -- struct mutex manager_arb; /* manager arbitration */ - struct worker *manager; /* L: purely informational */ - struct mutex attach_mutex; /* attach/detach exclusion */ - struct list_head workers; /* A: attached workers */ -@@ -295,6 +295,7 @@ static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf; - - static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list */ - static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */ -+static DECLARE_WAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go away */ - - static LIST_HEAD(workqueues); /* PR: list of all workqueues */ - static bool workqueue_freezing; /* PL: have wqs started freezing? */ -@@ -808,7 +809,7 @@ static bool need_to_create_worker(struct worker_pool *pool) - /* Do we have too many workers and should some go away? */ - static bool too_many_workers(struct worker_pool *pool) - { -- bool managing = mutex_is_locked(&pool->manager_arb); -+ bool managing = pool->flags & POOL_MANAGER_ACTIVE; - int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ - int nr_busy = pool->nr_workers - nr_idle; - -@@ -1952,24 +1953,17 @@ static bool manage_workers(struct worker *worker) - { - struct worker_pool *pool = worker->pool; - -- /* -- * Anyone who successfully grabs manager_arb wins the arbitration -- * and becomes the manager. mutex_trylock() on pool->manager_arb -- * failure while holding pool->lock reliably indicates that someone -- * else is managing the pool and the worker which failed trylock -- * can proceed to executing work items. This means that anyone -- * grabbing manager_arb is responsible for actually performing -- * manager duties. If manager_arb is grabbed and released without -- * actual management, the pool may stall indefinitely. -- */ -- if (!mutex_trylock(&pool->manager_arb)) -+ if (pool->flags & POOL_MANAGER_ACTIVE) - return false; -+ -+ pool->flags |= POOL_MANAGER_ACTIVE; - pool->manager = worker; - - maybe_create_worker(pool); - - pool->manager = NULL; -- mutex_unlock(&pool->manager_arb); -+ pool->flags &= ~POOL_MANAGER_ACTIVE; -+ wake_up(&wq_manager_wait); - return true; - } - -@@ -3119,7 +3113,6 @@ static int init_worker_pool(struct worker_pool *pool) - setup_timer(&pool->mayday_timer, pool_mayday_timeout, - (unsigned long)pool); - -- mutex_init(&pool->manager_arb); - mutex_init(&pool->attach_mutex); - INIT_LIST_HEAD(&pool->workers); - -@@ -3189,13 +3182,15 @@ static void put_unbound_pool(struct worker_pool *pool) - hash_del(&pool->hash_node); - - /* -- * Become the manager and destroy all workers. Grabbing -- * manager_arb prevents @pool's workers from blocking on -- * attach_mutex. -+ * Become the manager and destroy all workers. This prevents -+ * @pool's workers from blocking on attach_mutex. We're the last -+ * manager and @pool gets freed with the flag set. - */ -- mutex_lock(&pool->manager_arb); -- - spin_lock_irq(&pool->lock); -+ wait_event_lock_irq(wq_manager_wait, -+ !(pool->flags & POOL_MANAGER_ACTIVE), pool->lock); -+ pool->flags |= POOL_MANAGER_ACTIVE; -+ - while ((worker = first_idle_worker(pool))) - destroy_worker(worker); - WARN_ON(pool->nr_workers || pool->nr_idle); -@@ -3209,8 +3204,6 @@ static void put_unbound_pool(struct worker_pool *pool) - if (pool->detach_completion) - wait_for_completion(pool->detach_completion); - -- mutex_unlock(&pool->manager_arb); -- - /* shut down the timers */ - del_timer_sync(&pool->idle_timer); - del_timer_sync(&pool->mayday_timer); -diff --git a/lib/assoc_array.c b/lib/assoc_array.c -index 59fd7c0b119c..5cd093589c5a 100644 ---- a/lib/assoc_array.c -+++ b/lib/assoc_array.c -@@ -598,21 +598,31 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit, - if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0) - goto all_leaves_cluster_together; - -- /* Otherwise we can just insert a new node ahead of the old -- * one. -+ /* Otherwise all the old leaves cluster in the same slot, but -+ * the new leaf wants to go into a different slot - so we -+ * create a new node (n0) to hold the new leaf and a pointer to -+ * a new node (n1) holding all the old leaves. -+ * -+ * This can be done by falling through to the node splitting -+ * path. - */ -- goto present_leaves_cluster_but_not_new_leaf; -+ pr_devel("present leaves cluster but not new leaf\n"); - } - - split_node: - pr_devel("split node\n"); - -- /* We need to split the current node; we know that the node doesn't -- * simply contain a full set of leaves that cluster together (it -- * contains meta pointers and/or non-clustering leaves). -+ /* We need to split the current node. The node must contain anything -+ * from a single leaf (in the one leaf case, this leaf will cluster -+ * with the new leaf) and the rest meta-pointers, to all leaves, some -+ * of which may cluster. -+ * -+ * It won't contain the case in which all the current leaves plus the -+ * new leaves want to cluster in the same slot. - * - * We need to expel at least two leaves out of a set consisting of the -- * leaves in the node and the new leaf. -+ * leaves in the node and the new leaf. The current meta pointers can -+ * just be copied as they shouldn't cluster with any of the leaves. - * - * We need a new node (n0) to replace the current one and a new node to - * take the expelled nodes (n1). -@@ -717,33 +727,6 @@ found_slot_for_multiple_occupancy: - pr_devel("<--%s() = ok [split node]\n", __func__); - return true; - --present_leaves_cluster_but_not_new_leaf: -- /* All the old leaves cluster in the same slot, but the new leaf wants -- * to go into a different slot, so we create a new node to hold the new -- * leaf and a pointer to a new node holding all the old leaves. -- */ -- pr_devel("present leaves cluster but not new leaf\n"); -- -- new_n0->back_pointer = node->back_pointer; -- new_n0->parent_slot = node->parent_slot; -- new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; -- new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); -- new_n1->parent_slot = edit->segment_cache[0]; -- new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch; -- edit->adjust_count_on = new_n0; -- -- for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) -- new_n1->slots[i] = node->slots[i]; -- -- new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0); -- edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]]; -- -- edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot]; -- edit->set[0].to = assoc_array_node_to_ptr(new_n0); -- edit->excised_meta[0] = assoc_array_node_to_ptr(node); -- pr_devel("<--%s() = ok [insert node before]\n", __func__); -- return true; -- - all_leaves_cluster_together: - /* All the leaves, new and old, want to cluster together in this node - * in the same slot, so we have to replace this node with a shortcut to -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 5cab24f52825..a83688f8672e 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -329,6 +329,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0233: -+ case 0x10ec0236: - case 0x10ec0255: - case 0x10ec0256: - case 0x10ec0282: -@@ -909,6 +910,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = { - { 0x10ec0275, 0x1028, 0, "ALC3260" }, - { 0x10ec0899, 0x1028, 0, "ALC3861" }, - { 0x10ec0298, 0x1028, 0, "ALC3266" }, -+ { 0x10ec0236, 0x1028, 0, "ALC3204" }, - { 0x10ec0256, 0x1028, 0, "ALC3246" }, - { 0x10ec0225, 0x1028, 0, "ALC3253" }, - { 0x10ec0295, 0x1028, 0, "ALC3254" }, -@@ -3694,6 +3696,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) - alc_process_coef_fw(codec, coef0255_1); - alc_process_coef_fw(codec, coef0255); - break; -+ case 0x10ec0236: - case 0x10ec0256: - alc_process_coef_fw(codec, coef0256); - alc_process_coef_fw(codec, coef0255); -@@ -3774,6 +3777,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, - - - switch (codec->core.vendor_id) { -+ case 0x10ec0236: - case 0x10ec0255: - case 0x10ec0256: - alc_write_coef_idx(codec, 0x45, 0xc489); -@@ -3879,6 +3883,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) - case 0x10ec0295: - alc_process_coef_fw(codec, coef0225); - break; -+ case 0x10ec0236: - case 0x10ec0255: - case 0x10ec0256: - alc_process_coef_fw(codec, coef0255); -@@ -3962,6 +3967,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) - case 0x10ec0255: - alc_process_coef_fw(codec, coef0255); - break; -+ case 0x10ec0236: - case 0x10ec0256: - alc_process_coef_fw(codec, coef0256); - break; -@@ -4052,6 +4058,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) - case 0x10ec0255: - alc_process_coef_fw(codec, coef0255); - break; -+ case 0x10ec0236: - case 0x10ec0256: - alc_process_coef_fw(codec, coef0256); - break; -@@ -4119,6 +4126,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) - }; - - switch (codec->core.vendor_id) { -+ case 0x10ec0236: - case 0x10ec0255: - case 0x10ec0256: - alc_process_coef_fw(codec, coef0255); -@@ -4320,6 +4328,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec) - case 0x10ec0255: - alc_process_coef_fw(codec, alc255fw); - break; -+ case 0x10ec0236: - case 0x10ec0256: - alc_process_coef_fw(codec, alc256fw); - break; -@@ -5834,6 +5843,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { - ALC225_STANDARD_PINS, - {0x12, 0xb7a60130}, - {0x1b, 0x90170110}), -+ SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, -+ {0x12, 0x90a60140}, -+ {0x14, 0x90170110}, -+ {0x21, 0x02211020}), -+ SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, -+ {0x12, 0x90a60140}, -+ {0x14, 0x90170150}, -+ {0x21, 0x02211020}), - SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, - {0x14, 0x90170110}, - {0x21, 0x02211020}), -@@ -6208,6 +6225,7 @@ static int patch_alc269(struct hda_codec *codec) - case 0x10ec0255: - spec->codec_variant = ALC269_TYPE_ALC255; - break; -+ case 0x10ec0236: - case 0x10ec0256: - spec->codec_variant = ALC269_TYPE_ALC256; - spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ -@@ -7147,6 +7165,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { - HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269), -+ HDA_CODEC_ENTRY(0x10ec0236, "ALC236", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260), diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.96-97.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.96-97.patch deleted file mode 100644 index 458b9e310..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.96-97.patch +++ /dev/null @@ -1,1525 +0,0 @@ -diff --git a/Makefile b/Makefile -index 12dfe1dcbaca..fb1a40d64ba8 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 96 -+SUBLEVEL = 97 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi -index cc952cf8ec30..024f1b75b0a3 100644 ---- a/arch/arm/boot/dts/armada-375.dtsi -+++ b/arch/arm/boot/dts/armada-375.dtsi -@@ -176,9 +176,9 @@ - reg = <0x8000 0x1000>; - cache-unified; - cache-level = <2>; -- arm,double-linefill-incr = <1>; -+ arm,double-linefill-incr = <0>; - arm,double-linefill-wrap = <0>; -- arm,double-linefill = <1>; -+ arm,double-linefill = <0>; - prefetch-data = <1>; - }; - -diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild -index bd425302c97a..628a38a11a70 100644 ---- a/arch/arm/include/asm/Kbuild -+++ b/arch/arm/include/asm/Kbuild -@@ -36,4 +36,3 @@ generic-y += termbits.h - generic-y += termios.h - generic-y += timex.h - generic-y += trace_clock.h --generic-y += unaligned.h -diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h -new file mode 100644 -index 000000000000..ab905ffcf193 ---- /dev/null -+++ b/arch/arm/include/asm/unaligned.h -@@ -0,0 +1,27 @@ -+#ifndef __ASM_ARM_UNALIGNED_H -+#define __ASM_ARM_UNALIGNED_H -+ -+/* -+ * We generally want to set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS on ARMv6+, -+ * but we don't want to use linux/unaligned/access_ok.h since that can lead -+ * to traps on unaligned stm/ldm or strd/ldrd. -+ */ -+#include -+ -+#if defined(__LITTLE_ENDIAN) -+# include -+# include -+# include -+# define get_unaligned __get_unaligned_le -+# define put_unaligned __put_unaligned_le -+#elif defined(__BIG_ENDIAN) -+# include -+# include -+# include -+# define get_unaligned __get_unaligned_be -+# define put_unaligned __put_unaligned_be -+#else -+# error need to define endianess -+#endif -+ -+#endif /* __ASM_ARM_UNALIGNED_H */ -diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c -index a727282bfa99..761d7d64d643 100644 ---- a/arch/arm/mach-pxa/balloon3.c -+++ b/arch/arm/mach-pxa/balloon3.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c -index db20d25daaab..1b92a4112bd1 100644 ---- a/arch/arm/mach-pxa/colibri-pxa270-income.c -+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c -index 89f790dda93e..d1f12909f740 100644 ---- a/arch/arm/mach-pxa/corgi.c -+++ b/arch/arm/mach-pxa/corgi.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c -index 066e3a250ee0..5e50c53f1f4b 100644 ---- a/arch/arm/mach-pxa/trizeps4.c -+++ b/arch/arm/mach-pxa/trizeps4.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c -index 54122a983ae3..2cce92924068 100644 ---- a/arch/arm/mach-pxa/vpac270.c -+++ b/arch/arm/mach-pxa/vpac270.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c -index 30e62a3f0701..d757cfb5f8a6 100644 ---- a/arch/arm/mach-pxa/zeus.c -+++ b/arch/arm/mach-pxa/zeus.c -@@ -13,6 +13,7 @@ - - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c -index e20359a7433c..d7f0a7d87ef2 100644 ---- a/arch/arm/mach-pxa/zylonite.c -+++ b/arch/arm/mach-pxa/zylonite.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c -index ca7f0ac5f708..210826d5bba5 100644 ---- a/arch/arm64/kernel/traps.c -+++ b/arch/arm64/kernel/traps.c -@@ -129,7 +129,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) - for (i = -4; i < 1; i++) { - unsigned int val, bad; - -- bad = __get_user(val, &((u32 *)addr)[i]); -+ bad = get_user(val, &((u32 *)addr)[i]); - - if (!bad) - p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); -diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c -index 404d94c6c8bc..feba1b211898 100644 ---- a/drivers/base/power/wakeirq.c -+++ b/drivers/base/power/wakeirq.c -@@ -141,6 +141,13 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq) - struct wake_irq *wirq = _wirq; - int res; - -+ /* Maybe abort suspend? */ -+ if (irqd_is_wakeup_set(irq_get_irq_data(irq))) { -+ pm_wakeup_event(wirq->dev, 0); -+ -+ return IRQ_HANDLED; -+ } -+ - /* We don't want RPM_ASYNC or RPM_NOWAIT here */ - res = pm_runtime_resume(wirq->dev); - if (res < 0) -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c -index bb0da76051a1..e5da6f19b9b8 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c -@@ -284,6 +284,10 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work) - amdgpu_dpm_enable_vce(adev, false); - } else { - amdgpu_asic_set_vce_clocks(adev, 0, 0); -+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_PG_STATE_GATE); -+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_CG_STATE_GATE); - } - } else { - schedule_delayed_work(&adev->vce.idle_work, -@@ -315,6 +319,11 @@ static void amdgpu_vce_note_usage(struct amdgpu_device *adev) - amdgpu_dpm_enable_vce(adev, true); - } else { - amdgpu_asic_set_vce_clocks(adev, 53300, 40000); -+ amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_CG_STATE_UNGATE); -+ amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, -+ AMD_PG_STATE_UNGATE); -+ - } - } - } -diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c -index fed44d4e5b72..f4eaccb191d4 100644 ---- a/drivers/gpu/drm/msm/msm_gem_submit.c -+++ b/drivers/gpu/drm/msm/msm_gem_submit.c -@@ -34,10 +34,13 @@ static inline void __user *to_user_ptr(u64 address) - } - - static struct msm_gem_submit *submit_create(struct drm_device *dev, -- struct msm_gpu *gpu, int nr) -+ struct msm_gpu *gpu, uint32_t nr) - { - struct msm_gem_submit *submit; -- int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0])); -+ uint64_t sz = sizeof(*submit) + ((u64)nr * sizeof(submit->bos[0])); -+ -+ if (sz > SIZE_MAX) -+ return NULL; - - submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); - if (submit) { -diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c -index d7e3af671543..d8803c3bbfdc 100644 ---- a/drivers/i2c/busses/i2c-riic.c -+++ b/drivers/i2c/busses/i2c-riic.c -@@ -80,6 +80,7 @@ - #define ICIER_TEIE 0x40 - #define ICIER_RIE 0x20 - #define ICIER_NAKIE 0x10 -+#define ICIER_SPIE 0x08 - - #define ICSR2_NACKF 0x10 - -@@ -216,11 +217,10 @@ static irqreturn_t riic_tend_isr(int irq, void *data) - return IRQ_NONE; - } - -- if (riic->is_last || riic->err) -+ if (riic->is_last || riic->err) { -+ riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER); - writeb(ICCR2_SP, riic->base + RIIC_ICCR2); -- -- writeb(0, riic->base + RIIC_ICIER); -- complete(&riic->msg_done); -+ } - - return IRQ_HANDLED; - } -@@ -240,13 +240,13 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data) - - if (riic->bytes_left == 1) { - /* STOP must come before we set ACKBT! */ -- if (riic->is_last) -+ if (riic->is_last) { -+ riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER); - writeb(ICCR2_SP, riic->base + RIIC_ICCR2); -+ } - - riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3); - -- writeb(0, riic->base + RIIC_ICIER); -- complete(&riic->msg_done); - } else { - riic_clear_set_bit(riic, ICMR3_ACKBT, 0, RIIC_ICMR3); - } -@@ -259,6 +259,21 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data) - return IRQ_HANDLED; - } - -+static irqreturn_t riic_stop_isr(int irq, void *data) -+{ -+ struct riic_dev *riic = data; -+ -+ /* read back registers to confirm writes have fully propagated */ -+ writeb(0, riic->base + RIIC_ICSR2); -+ readb(riic->base + RIIC_ICSR2); -+ writeb(0, riic->base + RIIC_ICIER); -+ readb(riic->base + RIIC_ICIER); -+ -+ complete(&riic->msg_done); -+ -+ return IRQ_HANDLED; -+} -+ - static u32 riic_func(struct i2c_adapter *adap) - { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -@@ -326,6 +341,7 @@ static struct riic_irq_desc riic_irqs[] = { - { .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" }, - { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" }, - { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" }, -+ { .res_num = 3, .isr = riic_stop_isr, .name = "riic-stop" }, - { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, - }; - -diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c -index d407244fd1bc..bd0f5b195188 100644 ---- a/drivers/media/pci/bt8xx/dvb-bt8xx.c -+++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c -@@ -680,6 +680,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) - /* DST is not a frontend, attaching the ASIC */ - if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) { - pr_err("%s: Could not find a Twinhan DST\n", __func__); -+ kfree(state); - break; - } - /* Attach other DST peripherals if any */ -diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c -index 49658ca39e51..a851f20dca23 100644 ---- a/drivers/media/platform/exynos4-is/fimc-is.c -+++ b/drivers/media/platform/exynos4-is/fimc-is.c -@@ -815,12 +815,13 @@ static int fimc_is_probe(struct platform_device *pdev) - is->irq = irq_of_parse_and_map(dev->of_node, 0); - if (!is->irq) { - dev_err(dev, "no irq found\n"); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_iounmap; - } - - ret = fimc_is_get_clocks(is); - if (ret < 0) -- return ret; -+ goto err_iounmap; - - platform_set_drvdata(pdev, is); - -@@ -880,6 +881,8 @@ err_irq: - free_irq(is->irq, is); - err_clk: - fimc_is_put_clocks(is); -+err_iounmap: -+ iounmap(is->pmu_regs); - return ret; - } - -@@ -935,6 +938,7 @@ static int fimc_is_remove(struct platform_device *pdev) - fimc_is_unregister_subdevs(is); - vb2_dma_contig_cleanup_ctx(is->alloc_ctx); - fimc_is_put_clocks(is); -+ iounmap(is->pmu_regs); - fimc_is_debugfs_remove(is); - release_firmware(is->fw.f_w); - fimc_is_free_cpu_memory(is); -diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c -index 19b0293312a0..07670117f922 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-core.c -+++ b/drivers/media/usb/cx231xx/cx231xx-core.c -@@ -356,7 +356,12 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev, - */ - if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) || - (ven_req->bRequest == 0x5) || -- (ven_req->bRequest == 0x6))) { -+ (ven_req->bRequest == 0x6) || -+ -+ /* Internal Master 3 Bus can send -+ * and receive only 4 bytes per time -+ */ -+ (ven_req->bRequest == 0x2))) { - unsend_size = 0; - pdata = ven_req->pBuff; - -diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c -index 0d1825696153..405ce78c1ef4 100644 ---- a/drivers/mfd/ab8500-sysctrl.c -+++ b/drivers/mfd/ab8500-sysctrl.c -@@ -99,7 +99,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value) - u8 bank; - - if (sysctrl_dev == NULL) -- return -EINVAL; -+ return -EPROBE_DEFER; - - bank = (reg >> 8); - if (!valid_bank(bank)) -@@ -115,11 +115,13 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value) - u8 bank; - - if (sysctrl_dev == NULL) -- return -EINVAL; -+ return -EPROBE_DEFER; - - bank = (reg >> 8); -- if (!valid_bank(bank)) -+ if (!valid_bank(bank)) { -+ pr_err("invalid bank\n"); - return -EINVAL; -+ } - - return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank, - (u8)(reg & 0xFF), mask, value); -@@ -180,9 +182,15 @@ static int ab8500_sysctrl_remove(struct platform_device *pdev) - return 0; - } - -+static const struct of_device_id ab8500_sysctrl_match[] = { -+ { .compatible = "stericsson,ab8500-sysctrl", }, -+ {} -+}; -+ - static struct platform_driver ab8500_sysctrl_driver = { - .driver = { - .name = "ab8500-sysctrl", -+ .of_match_table = ab8500_sysctrl_match, - }, - .probe = ab8500_sysctrl_probe, - .remove = ab8500_sysctrl_remove, -diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c -index 9842199e2e6c..89a2dd4d212a 100644 ---- a/drivers/mfd/axp20x.c -+++ b/drivers/mfd/axp20x.c -@@ -164,14 +164,14 @@ static struct resource axp22x_pek_resources[] = { - static struct resource axp288_power_button_resources[] = { - { - .name = "PEK_DBR", -- .start = AXP288_IRQ_POKN, -- .end = AXP288_IRQ_POKN, -+ .start = AXP288_IRQ_POKP, -+ .end = AXP288_IRQ_POKP, - .flags = IORESOURCE_IRQ, - }, - { - .name = "PEK_DBF", -- .start = AXP288_IRQ_POKP, -- .end = AXP288_IRQ_POKP, -+ .start = AXP288_IRQ_POKN, -+ .end = AXP288_IRQ_POKN, - .flags = IORESOURCE_IRQ, - }, - }; -diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c -index 2ff39fbc70d1..df268365e04e 100644 ---- a/drivers/misc/mei/client.c -+++ b/drivers/misc/mei/client.c -@@ -1300,6 +1300,9 @@ int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request) - return -EOPNOTSUPP; - } - -+ if (!mei_cl_is_connected(cl)) -+ return -ENODEV; -+ - rets = pm_runtime_get(dev->dev); - if (rets < 0 && rets != -EINPROGRESS) { - pm_runtime_put_noidle(dev->dev); -diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c -index 6291d5042ef2..6fed41bd016a 100644 ---- a/drivers/mmc/host/s3cmci.c -+++ b/drivers/mmc/host/s3cmci.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - -diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c -index 9f713b832ba3..5c768c4627d3 100644 ---- a/drivers/platform/x86/intel_mid_thermal.c -+++ b/drivers/platform/x86/intel_mid_thermal.c -@@ -550,6 +550,7 @@ static const struct platform_device_id therm_id_table[] = { - { "msic_thermal", 1 }, - { } - }; -+MODULE_DEVICE_TABLE(platform, therm_id_table); - - static struct platform_driver mid_thermal_driver = { - .driver = { -diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c -index 84c13dffa3a8..e7a6f1222642 100644 ---- a/drivers/s390/block/dasd.c -+++ b/drivers/s390/block/dasd.c -@@ -1635,8 +1635,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, - /* check for for attention message */ - if (scsw_dstat(&irb->scsw) & DEV_STAT_ATTENTION) { - device = dasd_device_from_cdev_locked(cdev); -- device->discipline->check_attention(device, irb->esw.esw1.lpum); -- dasd_put_device(device); -+ if (!IS_ERR(device)) { -+ device->discipline->check_attention(device, -+ irb->esw.esw1.lpum); -+ dasd_put_device(device); -+ } - } - - if (!cqr) -diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c -index e4c243748a97..de33801ca31e 100644 ---- a/drivers/scsi/aacraid/aachba.c -+++ b/drivers/scsi/aacraid/aachba.c -@@ -2977,16 +2977,11 @@ static void aac_srb_callback(void *context, struct fib * fibptr) - return; - - BUG_ON(fibptr == NULL); -- dev = fibptr->dev; -- -- scsi_dma_unmap(scsicmd); - -- /* expose physical device if expose_physicald flag is on */ -- if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01) -- && expose_physicals > 0) -- aac_expose_phy_device(scsicmd); -+ dev = fibptr->dev; - - srbreply = (struct aac_srb_reply *) fib_data(fibptr); -+ - scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ - - if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) { -@@ -2999,158 +2994,176 @@ static void aac_srb_callback(void *context, struct fib * fibptr) - */ - scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) - - le32_to_cpu(srbreply->data_xfer_length)); -- /* -- * First check the fib status -- */ -+ } - -- if (le32_to_cpu(srbreply->status) != ST_OK) { -- int len; - -- printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); -- len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), -- SCSI_SENSE_BUFFERSIZE); -- scsicmd->result = DID_ERROR << 16 -- | COMMAND_COMPLETE << 8 -- | SAM_STAT_CHECK_CONDITION; -- memcpy(scsicmd->sense_buffer, -- srbreply->sense_data, len); -- } -+ scsi_dma_unmap(scsicmd); - -- /* -- * Next check the srb status -- */ -- switch ((le32_to_cpu(srbreply->srb_status))&0x3f) { -- case SRB_STATUS_ERROR_RECOVERY: -- case SRB_STATUS_PENDING: -- case SRB_STATUS_SUCCESS: -- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; -- break; -- case SRB_STATUS_DATA_OVERRUN: -- switch (scsicmd->cmnd[0]) { -- case READ_6: -- case WRITE_6: -- case READ_10: -- case WRITE_10: -- case READ_12: -- case WRITE_12: -- case READ_16: -- case WRITE_16: -- if (le32_to_cpu(srbreply->data_xfer_length) -- < scsicmd->underflow) -- printk(KERN_WARNING"aacraid: SCSI CMD underflow\n"); -- else -- printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n"); -- scsicmd->result = DID_ERROR << 16 -- | COMMAND_COMPLETE << 8; -- break; -- case INQUIRY: { -- scsicmd->result = DID_OK << 16 -- | COMMAND_COMPLETE << 8; -- break; -- } -- default: -- scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; -- break; -- } -- break; -- case SRB_STATUS_ABORTED: -- scsicmd->result = DID_ABORT << 16 | ABORT << 8; -- break; -- case SRB_STATUS_ABORT_FAILED: -- /* -- * Not sure about this one - but assuming the -- * hba was trying to abort for some reason -- */ -- scsicmd->result = DID_ERROR << 16 | ABORT << 8; -- break; -- case SRB_STATUS_PARITY_ERROR: -- scsicmd->result = DID_PARITY << 16 -- | MSG_PARITY_ERROR << 8; -- break; -- case SRB_STATUS_NO_DEVICE: -- case SRB_STATUS_INVALID_PATH_ID: -- case SRB_STATUS_INVALID_TARGET_ID: -- case SRB_STATUS_INVALID_LUN: -- case SRB_STATUS_SELECTION_TIMEOUT: -- scsicmd->result = DID_NO_CONNECT << 16 -- | COMMAND_COMPLETE << 8; -- break; -+ /* expose physical device if expose_physicald flag is on */ -+ if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01) -+ && expose_physicals > 0) -+ aac_expose_phy_device(scsicmd); - -- case SRB_STATUS_COMMAND_TIMEOUT: -- case SRB_STATUS_TIMEOUT: -- scsicmd->result = DID_TIME_OUT << 16 -- | COMMAND_COMPLETE << 8; -- break; -+ /* -+ * First check the fib status -+ */ - -- case SRB_STATUS_BUSY: -- scsicmd->result = DID_BUS_BUSY << 16 -- | COMMAND_COMPLETE << 8; -- break; -+ if (le32_to_cpu(srbreply->status) != ST_OK) { -+ int len; - -- case SRB_STATUS_BUS_RESET: -- scsicmd->result = DID_RESET << 16 -- | COMMAND_COMPLETE << 8; -- break; -+ pr_warn("aac_srb_callback: srb failed, status = %d\n", -+ le32_to_cpu(srbreply->status)); -+ len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), -+ SCSI_SENSE_BUFFERSIZE); -+ scsicmd->result = DID_ERROR << 16 -+ | COMMAND_COMPLETE << 8 -+ | SAM_STAT_CHECK_CONDITION; -+ memcpy(scsicmd->sense_buffer, -+ srbreply->sense_data, len); -+ } - -- case SRB_STATUS_MESSAGE_REJECTED: -+ /* -+ * Next check the srb status -+ */ -+ switch ((le32_to_cpu(srbreply->srb_status))&0x3f) { -+ case SRB_STATUS_ERROR_RECOVERY: -+ case SRB_STATUS_PENDING: -+ case SRB_STATUS_SUCCESS: -+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; -+ break; -+ case SRB_STATUS_DATA_OVERRUN: -+ switch (scsicmd->cmnd[0]) { -+ case READ_6: -+ case WRITE_6: -+ case READ_10: -+ case WRITE_10: -+ case READ_12: -+ case WRITE_12: -+ case READ_16: -+ case WRITE_16: -+ if (le32_to_cpu(srbreply->data_xfer_length) -+ < scsicmd->underflow) -+ pr_warn("aacraid: SCSI CMD underflow\n"); -+ else -+ pr_warn("aacraid: SCSI CMD Data Overrun\n"); - scsicmd->result = DID_ERROR << 16 -- | MESSAGE_REJECT << 8; -+ | COMMAND_COMPLETE << 8; -+ break; -+ case INQUIRY: -+ scsicmd->result = DID_OK << 16 -+ | COMMAND_COMPLETE << 8; - break; -- case SRB_STATUS_REQUEST_FLUSHED: -- case SRB_STATUS_ERROR: -- case SRB_STATUS_INVALID_REQUEST: -- case SRB_STATUS_REQUEST_SENSE_FAILED: -- case SRB_STATUS_NO_HBA: -- case SRB_STATUS_UNEXPECTED_BUS_FREE: -- case SRB_STATUS_PHASE_SEQUENCE_FAILURE: -- case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: -- case SRB_STATUS_DELAYED_RETRY: -- case SRB_STATUS_BAD_FUNCTION: -- case SRB_STATUS_NOT_STARTED: -- case SRB_STATUS_NOT_IN_USE: -- case SRB_STATUS_FORCE_ABORT: -- case SRB_STATUS_DOMAIN_VALIDATION_FAIL: - default: -+ scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; -+ break; -+ } -+ break; -+ case SRB_STATUS_ABORTED: -+ scsicmd->result = DID_ABORT << 16 | ABORT << 8; -+ break; -+ case SRB_STATUS_ABORT_FAILED: -+ /* -+ * Not sure about this one - but assuming the -+ * hba was trying to abort for some reason -+ */ -+ scsicmd->result = DID_ERROR << 16 | ABORT << 8; -+ break; -+ case SRB_STATUS_PARITY_ERROR: -+ scsicmd->result = DID_PARITY << 16 -+ | MSG_PARITY_ERROR << 8; -+ break; -+ case SRB_STATUS_NO_DEVICE: -+ case SRB_STATUS_INVALID_PATH_ID: -+ case SRB_STATUS_INVALID_TARGET_ID: -+ case SRB_STATUS_INVALID_LUN: -+ case SRB_STATUS_SELECTION_TIMEOUT: -+ scsicmd->result = DID_NO_CONNECT << 16 -+ | COMMAND_COMPLETE << 8; -+ break; -+ -+ case SRB_STATUS_COMMAND_TIMEOUT: -+ case SRB_STATUS_TIMEOUT: -+ scsicmd->result = DID_TIME_OUT << 16 -+ | COMMAND_COMPLETE << 8; -+ break; -+ -+ case SRB_STATUS_BUSY: -+ scsicmd->result = DID_BUS_BUSY << 16 -+ | COMMAND_COMPLETE << 8; -+ break; -+ -+ case SRB_STATUS_BUS_RESET: -+ scsicmd->result = DID_RESET << 16 -+ | COMMAND_COMPLETE << 8; -+ break; -+ -+ case SRB_STATUS_MESSAGE_REJECTED: -+ scsicmd->result = DID_ERROR << 16 -+ | MESSAGE_REJECT << 8; -+ break; -+ case SRB_STATUS_REQUEST_FLUSHED: -+ case SRB_STATUS_ERROR: -+ case SRB_STATUS_INVALID_REQUEST: -+ case SRB_STATUS_REQUEST_SENSE_FAILED: -+ case SRB_STATUS_NO_HBA: -+ case SRB_STATUS_UNEXPECTED_BUS_FREE: -+ case SRB_STATUS_PHASE_SEQUENCE_FAILURE: -+ case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: -+ case SRB_STATUS_DELAYED_RETRY: -+ case SRB_STATUS_BAD_FUNCTION: -+ case SRB_STATUS_NOT_STARTED: -+ case SRB_STATUS_NOT_IN_USE: -+ case SRB_STATUS_FORCE_ABORT: -+ case SRB_STATUS_DOMAIN_VALIDATION_FAIL: -+ default: - #ifdef AAC_DETAILED_STATUS_INFO -- printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n", -- le32_to_cpu(srbreply->srb_status) & 0x3F, -- aac_get_status_string( -- le32_to_cpu(srbreply->srb_status) & 0x3F), -- scsicmd->cmnd[0], -- le32_to_cpu(srbreply->scsi_status)); -+ pr_info("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x -scsi status 0x%x\n", -+ le32_to_cpu(srbreply->srb_status) & 0x3F, -+ aac_get_status_string( -+ le32_to_cpu(srbreply->srb_status) & 0x3F), -+ scsicmd->cmnd[0], -+ le32_to_cpu(srbreply->scsi_status)); - #endif -- if ((scsicmd->cmnd[0] == ATA_12) -- || (scsicmd->cmnd[0] == ATA_16)) { -- if (scsicmd->cmnd[2] & (0x01 << 5)) { -- scsicmd->result = DID_OK << 16 -- | COMMAND_COMPLETE << 8; -- break; -- } else { -- scsicmd->result = DID_ERROR << 16 -- | COMMAND_COMPLETE << 8; -- break; -- } -+ /* -+ * When the CC bit is SET by the host in ATA pass thru CDB, -+ * driver is supposed to return DID_OK -+ * -+ * When the CC bit is RESET by the host, driver should -+ * return DID_ERROR -+ */ -+ if ((scsicmd->cmnd[0] == ATA_12) -+ || (scsicmd->cmnd[0] == ATA_16)) { -+ -+ if (scsicmd->cmnd[2] & (0x01 << 5)) { -+ scsicmd->result = DID_OK << 16 -+ | COMMAND_COMPLETE << 8; -+ break; - } else { - scsicmd->result = DID_ERROR << 16 - | COMMAND_COMPLETE << 8; -- break; -+ break; - } -+ } else { -+ scsicmd->result = DID_ERROR << 16 -+ | COMMAND_COMPLETE << 8; -+ break; - } -- if (le32_to_cpu(srbreply->scsi_status) -- == SAM_STAT_CHECK_CONDITION) { -- int len; -+ } -+ if (le32_to_cpu(srbreply->scsi_status) -+ == SAM_STAT_CHECK_CONDITION) { -+ int len; - -- scsicmd->result |= SAM_STAT_CHECK_CONDITION; -- len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), -- SCSI_SENSE_BUFFERSIZE); -+ scsicmd->result |= SAM_STAT_CHECK_CONDITION; -+ len = min_t(u32, le32_to_cpu(srbreply->sense_data_size), -+ SCSI_SENSE_BUFFERSIZE); - #ifdef AAC_DETAILED_STATUS_INFO -- printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", -- le32_to_cpu(srbreply->status), len); -+ pr_warn("aac_srb_callback: check condition, status = %d len=%d\n", -+ le32_to_cpu(srbreply->status), len); - #endif -- memcpy(scsicmd->sense_buffer, -- srbreply->sense_data, len); -- } -+ memcpy(scsicmd->sense_buffer, -+ srbreply->sense_data, len); - } -+ - /* - * OR in the scsi status (already shifted up a bit) - */ -diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h -index 80f8ec529424..8ed4558238fc 100644 ---- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h -+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h -@@ -1063,23 +1063,21 @@ struct hsm_action_item { - * \retval buffer - */ - static inline char *hai_dump_data_field(struct hsm_action_item *hai, -- char *buffer, int len) -+ char *buffer, size_t len) - { -- int i, sz, data_len; -+ int i, data_len; - char *ptr; - - ptr = buffer; -- sz = len; - data_len = hai->hai_len - sizeof(*hai); -- for (i = 0 ; (i < data_len) && (sz > 0) ; i++) { -- int cnt; -- -- cnt = snprintf(ptr, sz, "%.2X", -- (unsigned char)hai->hai_data[i]); -- ptr += cnt; -- sz -= cnt; -+ for (i = 0; (i < data_len) && (len > 2); i++) { -+ snprintf(ptr, 3, "%02X", (unsigned char)hai->hai_data[i]); -+ ptr += 2; -+ len -= 2; - } -+ - *ptr = '\0'; -+ - return buffer; - } - -diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c -index 7f8c70056ffd..040553d6e316 100644 ---- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c -+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c -@@ -550,6 +550,13 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, - if (lock == NULL) - return NULL; - -+ if (lock->l_export && lock->l_export->exp_failed) { -+ CDEBUG(D_INFO, "lock export failed: lock %p, exp %p\n", -+ lock, lock->l_export); -+ LDLM_LOCK_PUT(lock); -+ return NULL; -+ } -+ - /* It's unlikely but possible that someone marked the lock as - * destroyed after we did handle2object on it */ - if (flags == 0 && ((lock->l_flags & LDLM_FL_DESTROYED) == 0)) { -diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c -index 3da4c01e2159..adeefb31cbad 100644 ---- a/drivers/staging/lustre/lustre/llite/rw26.c -+++ b/drivers/staging/lustre/lustre/llite/rw26.c -@@ -376,6 +376,10 @@ static ssize_t ll_direct_IO_26(struct kiocb *iocb, struct iov_iter *iter, - if (!lli->lli_has_smd) - return -EBADF; - -+ /* Check EOF by ourselves */ -+ if (iov_iter_rw(iter) == READ && file_offset >= i_size_read(inode)) -+ return 0; -+ - /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */ - if ((file_offset & ~CFS_PAGE_MASK) || (count & ~CFS_PAGE_MASK)) - return -EINVAL; -diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c -index f45898f17793..6d3c25ccb297 100644 ---- a/drivers/staging/lustre/lustre/ptlrpc/service.c -+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c -@@ -1240,20 +1240,15 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt, - * it may hit swab race at LU-1044. */ - if (req->rq_ops->hpreq_check) { - rc = req->rq_ops->hpreq_check(req); -- /** -- * XXX: Out of all current -- * ptlrpc_hpreq_ops::hpreq_check(), only -- * ldlm_cancel_hpreq_check() can return an error code; -- * other functions assert in similar places, which seems -- * odd. What also does not seem right is that handlers -- * for those RPCs do not assert on the same checks, but -- * rather handle the error cases. e.g. see -- * ost_rw_hpreq_check(), and ost_brw_read(), -- * ost_brw_write(). -+ if (rc == -ESTALE) { -+ req->rq_status = rc; -+ ptlrpc_error(req); -+ } -+ /** can only return error, -+ * 0 for normal request, -+ * or 1 for high priority request - */ -- if (rc < 0) -- return rc; -- LASSERT(rc == 0 || rc == 1); -+ LASSERT(rc <= 1); - } - - spin_lock_bh(&req->rq_export->exp_rpc_lock); -diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h -index d374824c4f33..7b16c05b5e8b 100644 ---- a/drivers/staging/rtl8712/ieee80211.h -+++ b/drivers/staging/rtl8712/ieee80211.h -@@ -143,52 +143,52 @@ struct ieee_ibss_seq { - }; - - struct ieee80211_hdr { -- u16 frame_ctl; -- u16 duration_id; -+ __le16 frame_ctl; -+ __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; -- u16 seq_ctl; -+ __le16 seq_ctl; - u8 addr4[ETH_ALEN]; --} __packed; -+} __packed __aligned(2); - - struct ieee80211_hdr_3addr { -- u16 frame_ctl; -- u16 duration_id; -+ __le16 frame_ctl; -+ __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; -- u16 seq_ctl; --} __packed; -+ __le16 seq_ctl; -+} __packed __aligned(2); - - - struct ieee80211_hdr_qos { -- u16 frame_ctl; -- u16 duration_id; -+ __le16 frame_ctl; -+ __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; -- u16 seq_ctl; -+ __le16 seq_ctl; - u8 addr4[ETH_ALEN]; -- u16 qc; --} __packed; -+ __le16 qc; -+} __packed __aligned(2); - - struct ieee80211_hdr_3addr_qos { -- u16 frame_ctl; -- u16 duration_id; -+ __le16 frame_ctl; -+ __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; -- u16 seq_ctl; -- u16 qc; -+ __le16 seq_ctl; -+ __le16 qc; - } __packed; - - struct eapol { - u8 snap[6]; -- u16 ethertype; -+ __be16 ethertype; - u8 version; - u8 type; -- u16 length; -+ __le16 length; - } __packed; - - -@@ -528,13 +528,13 @@ struct ieee80211_security { - */ - - struct ieee80211_header_data { -- u16 frame_ctl; -- u16 duration_id; -+ __le16 frame_ctl; -+ __le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; -- u16 seq_ctrl; --}; -+ __le16 seq_ctrl; -+} __packed __aligned(2); - - #define BEACON_PROBE_SSID_ID_POSITION 12 - -@@ -566,18 +566,18 @@ struct ieee80211_info_element { - /* - * These are the data types that can make up management packets - * -- u16 auth_algorithm; -- u16 auth_sequence; -- u16 beacon_interval; -- u16 capability; -+ __le16 auth_algorithm; -+ __le16 auth_sequence; -+ __le16 beacon_interval; -+ __le16 capability; - u8 current_ap[ETH_ALEN]; -- u16 listen_interval; -+ __le16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __packed; -- u32 time_stamp[2]; -- u16 reason; -- u16 status; -+ __le32 time_stamp[2]; -+ __le16 reason; -+ __le16 status; - */ - - #define IEEE80211_DEFAULT_TX_ESSID "Penguin" -@@ -585,16 +585,16 @@ struct ieee80211_info_element { - - struct ieee80211_authentication { - struct ieee80211_header_data header; -- u16 algorithm; -- u16 transaction; -- u16 status; -+ __le16 algorithm; -+ __le16 transaction; -+ __le16 status; - } __packed; - - struct ieee80211_probe_response { - struct ieee80211_header_data header; -- u32 time_stamp[2]; -- u16 beacon_interval; -- u16 capability; -+ __le32 time_stamp[2]; -+ __le16 beacon_interval; -+ __le16 capability; - struct ieee80211_info_element info_element; - } __packed; - -@@ -604,16 +604,16 @@ struct ieee80211_probe_request { - - struct ieee80211_assoc_request_frame { - struct ieee80211_hdr_3addr header; -- u16 capability; -- u16 listen_interval; -+ __le16 capability; -+ __le16 listen_interval; - struct ieee80211_info_element_hdr info_element; - } __packed; - - struct ieee80211_assoc_response_frame { - struct ieee80211_hdr_3addr header; -- u16 capability; -- u16 status; -- u16 aid; -+ __le16 capability; -+ __le16 status; -+ __le16 aid; - } __packed; - - struct ieee80211_txb { -diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c -index 68d65d230fe3..d3ad89c7b8af 100644 ---- a/drivers/staging/rtl8712/rtl871x_xmit.c -+++ b/drivers/staging/rtl8712/rtl871x_xmit.c -@@ -339,7 +339,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite - * some settings above.*/ - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) -- pattrib->priority = (txdesc.txdw1 >> QSEL_SHT) & 0x1f; -+ pattrib->priority = -+ (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; - return _SUCCESS; - } - -@@ -479,7 +480,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; -- u16 *fctrl = &pwlanhdr->frame_ctl; -+ __le16 *fctrl = &pwlanhdr->frame_ctl; - - memset(hdr, 0, WLANHDR_OFFSET); - SetFrameSubType(fctrl, pattrib->subtype); -@@ -568,7 +569,7 @@ static sint r8712_put_snap(u8 *data, u16 h_proto) - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; -- *(u16 *)(data + SNAP_SIZE) = htons(h_proto); -+ *(__be16 *)(data + SNAP_SIZE) = htons(h_proto); - return SNAP_SIZE + sizeof(u16); - } - -diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c -index e12bd3635f83..2dd285827169 100644 ---- a/drivers/xen/manage.c -+++ b/drivers/xen/manage.c -@@ -275,8 +275,16 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, - err = xenbus_transaction_start(&xbt); - if (err) - return; -- if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { -- pr_err("Unable to read sysrq code in control/sysrq\n"); -+ err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key); -+ if (err < 0) { -+ /* -+ * The Xenstore watch fires directly after registering it and -+ * after a suspend/resume cycle. So ENOENT is no error but -+ * might happen in those cases. -+ */ -+ if (err != -ENOENT) -+ pr_err("Error %d reading sysrq code in control/sysrq\n", -+ err); - xenbus_transaction_end(xbt, 1); - return; - } -diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c -index 297e05c9e2b0..49a0d6b027c1 100644 ---- a/fs/cifs/dir.c -+++ b/fs/cifs/dir.c -@@ -193,7 +193,8 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon) - struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); - int i; - -- if (unlikely(direntry->d_name.len > -+ if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength && -+ direntry->d_name.len > - le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength))) - return -ENAMETOOLONG; - -@@ -509,7 +510,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, - - rc = check_name(direntry, tcon); - if (rc) -- goto out_free_xid; -+ goto out; - - server = tcon->ses->server; - -diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c -index 84cd77663e1f..1ba82dc5afa3 100644 ---- a/fs/ext4/mballoc.c -+++ b/fs/ext4/mballoc.c -@@ -2136,8 +2136,10 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac) - * We search using buddy data only if the order of the request - * is greater than equal to the sbi_s_mb_order2_reqs - * You can tune it via /sys/fs/ext4//mb_order2_req -+ * We also support searching for power-of-two requests only for -+ * requests upto maximum buddy size we have constructed. - */ -- if (i >= sbi->s_mb_order2_reqs) { -+ if (i >= sbi->s_mb_order2_reqs && i <= sb->s_blocksize_bits + 2) { - /* - * This should tell if fe_len is exactly power of 2 - */ -@@ -2207,7 +2209,7 @@ repeat: - } - - ac->ac_groups_scanned++; -- if (cr == 0 && ac->ac_2order < sb->s_blocksize_bits+2) -+ if (cr == 0) - ext4_mb_simple_scan_group(ac, &e4b); - else if (cr == 1 && sbi->s_stripe && - !(ac->ac_g_ex.fe_len % sbi->s_stripe)) -diff --git a/fs/ext4/super.c b/fs/ext4/super.c -index 32941cd6d34b..8bdb0cc2722f 100644 ---- a/fs/ext4/super.c -+++ b/fs/ext4/super.c -@@ -2499,9 +2499,9 @@ static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) - - if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group) - ret = sbi->s_stripe; -- else if (stripe_width <= sbi->s_blocks_per_group) -+ else if (stripe_width && stripe_width <= sbi->s_blocks_per_group) - ret = stripe_width; -- else if (stride <= sbi->s_blocks_per_group) -+ else if (stride && stride <= sbi->s_blocks_per_group) - ret = stride; - else - ret = 0; -diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c -index 86181d6526dc..93e6f029a322 100644 ---- a/fs/ocfs2/alloc.c -+++ b/fs/ocfs2/alloc.c -@@ -7270,13 +7270,24 @@ out: - - static int ocfs2_trim_extent(struct super_block *sb, - struct ocfs2_group_desc *gd, -- u32 start, u32 count) -+ u64 group, u32 start, u32 count) - { - u64 discard, bcount; -+ struct ocfs2_super *osb = OCFS2_SB(sb); - - bcount = ocfs2_clusters_to_blocks(sb, count); -- discard = le64_to_cpu(gd->bg_blkno) + -- ocfs2_clusters_to_blocks(sb, start); -+ discard = ocfs2_clusters_to_blocks(sb, start); -+ -+ /* -+ * For the first cluster group, the gd->bg_blkno is not at the start -+ * of the group, but at an offset from the start. If we add it while -+ * calculating discard for first group, we will wrongly start fstrim a -+ * few blocks after the desried start block and the range can cross -+ * over into the next cluster group. So, add it only if this is not -+ * the first cluster group. -+ */ -+ if (group != osb->first_cluster_group_blkno) -+ discard += le64_to_cpu(gd->bg_blkno); - - trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); - -@@ -7284,7 +7295,7 @@ static int ocfs2_trim_extent(struct super_block *sb, - } - - static int ocfs2_trim_group(struct super_block *sb, -- struct ocfs2_group_desc *gd, -+ struct ocfs2_group_desc *gd, u64 group, - u32 start, u32 max, u32 minbits) - { - int ret = 0, count = 0, next; -@@ -7303,7 +7314,7 @@ static int ocfs2_trim_group(struct super_block *sb, - next = ocfs2_find_next_bit(bitmap, max, start); - - if ((next - start) >= minbits) { -- ret = ocfs2_trim_extent(sb, gd, -+ ret = ocfs2_trim_extent(sb, gd, group, - start, next - start); - if (ret < 0) { - mlog_errno(ret); -@@ -7401,7 +7412,8 @@ int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range) - } - - gd = (struct ocfs2_group_desc *)gd_bh->b_data; -- cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); -+ cnt = ocfs2_trim_group(sb, gd, group, -+ first_bit, last_bit, minlen); - brelse(gd_bh); - gd_bh = NULL; - if (cnt < 0) { -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -index 554522934c44..faa2a3f017f8 100644 ---- a/lib/asn1_decoder.c -+++ b/lib/asn1_decoder.c -@@ -283,6 +283,9 @@ next_op: - if (unlikely(len > datalen - dp)) - goto data_overrun_error; - } -+ } else { -+ if (unlikely(len > datalen - dp)) -+ goto data_overrun_error; - } - - if (flags & FLAG_CONS) { -diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c -index 880a7d1d27d2..4ccff66523c9 100644 ---- a/samples/trace_events/trace-events-sample.c -+++ b/samples/trace_events/trace-events-sample.c -@@ -78,28 +78,36 @@ static int simple_thread_fn(void *arg) - } - - static DEFINE_MUTEX(thread_mutex); -+static int simple_thread_cnt; - - void foo_bar_reg(void) - { -+ mutex_lock(&thread_mutex); -+ if (simple_thread_cnt++) -+ goto out; -+ - pr_info("Starting thread for foo_bar_fn\n"); - /* - * We shouldn't be able to start a trace when the module is - * unloading (there's other locks to prevent that). But - * for consistency sake, we still take the thread_mutex. - */ -- mutex_lock(&thread_mutex); - simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); -+ out: - mutex_unlock(&thread_mutex); - } - - void foo_bar_unreg(void) - { -- pr_info("Killing thread for foo_bar_fn\n"); -- /* protect against module unloading */ - mutex_lock(&thread_mutex); -+ if (--simple_thread_cnt) -+ goto out; -+ -+ pr_info("Killing thread for foo_bar_fn\n"); - if (simple_tsk_fn) - kthread_stop(simple_tsk_fn); - simple_tsk_fn = NULL; -+ out: - mutex_unlock(&thread_mutex); - } - -diff --git a/security/keys/keyring.c b/security/keys/keyring.c -index ef828238cdc0..d5264f950ce1 100644 ---- a/security/keys/keyring.c -+++ b/security/keys/keyring.c -@@ -452,34 +452,33 @@ static long keyring_read(const struct key *keyring, - char __user *buffer, size_t buflen) - { - struct keyring_read_iterator_context ctx; -- unsigned long nr_keys; -- int ret; -+ long ret; - - kenter("{%d},,%zu", key_serial(keyring), buflen); - - if (buflen & (sizeof(key_serial_t) - 1)) - return -EINVAL; - -- nr_keys = keyring->keys.nr_leaves_on_tree; -- if (nr_keys == 0) -- return 0; -- -- /* Calculate how much data we could return */ -- if (!buffer || !buflen) -- return nr_keys * sizeof(key_serial_t); -- -- /* Copy the IDs of the subscribed keys into the buffer */ -- ctx.buffer = (key_serial_t __user *)buffer; -- ctx.buflen = buflen; -- ctx.count = 0; -- ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); -- if (ret < 0) { -- kleave(" = %d [iterate]", ret); -- return ret; -+ /* Copy as many key IDs as fit into the buffer */ -+ if (buffer && buflen) { -+ ctx.buffer = (key_serial_t __user *)buffer; -+ ctx.buflen = buflen; -+ ctx.count = 0; -+ ret = assoc_array_iterate(&keyring->keys, -+ keyring_read_iterator, &ctx); -+ if (ret < 0) { -+ kleave(" = %ld [iterate]", ret); -+ return ret; -+ } - } - -- kleave(" = %zu [ok]", ctx.count); -- return ctx.count; -+ /* Return the size of the buffer needed */ -+ ret = keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t); -+ if (ret <= buflen) -+ kleave("= %ld [ok]", ret); -+ else -+ kleave("= %ld [buffer too small]", ret); -+ return ret; - } - - /* -diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c -index e847b9923c19..b36de76f24e2 100644 ---- a/sound/core/seq/seq_clientmgr.c -+++ b/sound/core/seq/seq_clientmgr.c -@@ -676,7 +676,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client, - if (atomic) - read_lock(&grp->list_lock); - else -- down_read(&grp->list_mutex); -+ down_read_nested(&grp->list_mutex, hop); - list_for_each_entry(subs, &grp->list_head, src_list) { - /* both ports ready? */ - if (atomic_read(&subs->ref_count) != 2) -diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c -index 2e908225d754..0b4b028e8e98 100644 ---- a/sound/core/timer_compat.c -+++ b/sound/core/timer_compat.c -@@ -106,7 +106,8 @@ enum { - #endif /* CONFIG_X86_X32 */ - }; - --static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -+static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, -+ unsigned long arg) - { - void __user *argp = compat_ptr(arg); - -@@ -127,7 +128,7 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns - case SNDRV_TIMER_IOCTL_PAUSE: - case SNDRV_TIMER_IOCTL_PAUSE_OLD: - case SNDRV_TIMER_IOCTL_NEXT_DEVICE: -- return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); -+ return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); - case SNDRV_TIMER_IOCTL_INFO32: - return snd_timer_user_info_compat(file, argp); - case SNDRV_TIMER_IOCTL_STATUS32: -@@ -139,3 +140,15 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns - } - return -ENOIOCTLCMD; - } -+ -+static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ struct snd_timer_user *tu = file->private_data; -+ long ret; -+ -+ mutex_lock(&tu->ioctl_lock); -+ ret = __snd_timer_user_ioctl_compat(file, cmd, arg); -+ mutex_unlock(&tu->ioctl_lock); -+ return ret; -+} -diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c -index fcf05b254ecd..0b9e13eb0a0a 100644 ---- a/sound/soc/codecs/adau17x1.c -+++ b/sound/soc/codecs/adau17x1.c -@@ -89,6 +89,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, - return 0; - } - -+static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); -+ struct adau *adau = snd_soc_codec_get_drvdata(codec); -+ -+ /* -+ * If we are capturing, toggle the ADOSR bit in Converter Control 0 to -+ * avoid losing SNR (workaround from ADI). This must be done after -+ * the ADC(s) have been enabled. According to the data sheet, it is -+ * normally illegal to set this bit when the sampling rate is 96 kHz, -+ * but according to ADI it is acceptable for this workaround. -+ */ -+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, -+ ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR); -+ regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, -+ ADAU17X1_CONVERTER0_ADOSR, 0); -+ -+ return 0; -+} -+ - static const char * const adau17x1_mono_stereo_text[] = { - "Stereo", - "Mono Left Channel (L+R)", -@@ -120,7 +141,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = { - SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0, - &adau17x1_dac_mode_mux), - -- SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0), -+ SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0, -+ adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0), - SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0), - SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0), -diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h -index e13583e6ff56..6b46461cdc03 100644 ---- a/sound/soc/codecs/adau17x1.h -+++ b/sound/soc/codecs/adau17x1.h -@@ -123,5 +123,7 @@ bool adau17x1_has_dsp(struct adau *adau); - - #define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7 - -+#define ADAU17X1_CONVERTER0_ADOSR BIT(3) -+ - - #endif -diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build -index 928e110179cb..34faecf774ae 100644 ---- a/tools/perf/scripts/perl/Perf-Trace-Util/Build -+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build -@@ -1,3 +1,5 @@ - libperf-y += Context.o - --CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default -+CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -+CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef -+CFLAGS_Context.o += -Wno-switch-default -Wno-shadow -diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c -index 38304b7e4f81..e81dfb2e239c 100644 ---- a/tools/perf/util/parse-events.c -+++ b/tools/perf/util/parse-events.c -@@ -291,10 +291,11 @@ __add_event(struct list_head *list, int *idx, - - event_attr_init(attr); - -- evsel = perf_evsel__new_idx(attr, (*idx)++); -+ evsel = perf_evsel__new_idx(attr, *idx); - if (!evsel) - return NULL; - -+ (*idx)++; - evsel->cpus = cpu_map__get(cpus); - evsel->own_cpus = cpu_map__get(cpus); - diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.97-98.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.97-98.patch deleted file mode 100644 index 38d2d5fa5..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.97-98.patch +++ /dev/null @@ -1,1881 +0,0 @@ -diff --git a/Makefile b/Makefile -index fb1a40d64ba8..5d62e23347f9 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 97 -+SUBLEVEL = 98 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig -index c5e1943e5427..09ebd37e01e0 100644 ---- a/arch/arm/configs/omap2plus_defconfig -+++ b/arch/arm/configs/omap2plus_defconfig -@@ -221,6 +221,7 @@ CONFIG_SERIO=m - CONFIG_SERIAL_8250=y - CONFIG_SERIAL_8250_CONSOLE=y - CONFIG_SERIAL_8250_NR_UARTS=32 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=6 - CONFIG_SERIAL_8250_EXTENDED=y - CONFIG_SERIAL_8250_MANY_PORTS=y - CONFIG_SERIAL_8250_SHARE_IRQ=y -diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c -index bc698383e822..c92b535150a0 100644 ---- a/arch/arm/kernel/traps.c -+++ b/arch/arm/kernel/traps.c -@@ -132,30 +132,26 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - set_fs(fs); - } - --static void dump_instr(const char *lvl, struct pt_regs *regs) -+static void __dump_instr(const char *lvl, struct pt_regs *regs) - { - unsigned long addr = instruction_pointer(regs); - const int thumb = thumb_mode(regs); - const int width = thumb ? 4 : 8; -- mm_segment_t fs; - char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; - int i; - - /* -- * We need to switch to kernel mode so that we can use __get_user -- * to safely read from kernel space. Note that we now dump the -- * code first, just in case the backtrace kills us. -+ * Note that we now dump the code first, just in case the backtrace -+ * kills us. - */ -- fs = get_fs(); -- set_fs(KERNEL_DS); - - for (i = -4; i < 1 + !!thumb; i++) { - unsigned int val, bad; - - if (thumb) -- bad = __get_user(val, &((u16 *)addr)[i]); -+ bad = get_user(val, &((u16 *)addr)[i]); - else -- bad = __get_user(val, &((u32 *)addr)[i]); -+ bad = get_user(val, &((u32 *)addr)[i]); - - if (!bad) - p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", -@@ -166,8 +162,20 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) - } - } - printk("%sCode: %s\n", lvl, str); -+} - -- set_fs(fs); -+static void dump_instr(const char *lvl, struct pt_regs *regs) -+{ -+ mm_segment_t fs; -+ -+ if (!user_mode(regs)) { -+ fs = get_fs(); -+ set_fs(KERNEL_DS); -+ __dump_instr(lvl, regs); -+ set_fs(fs); -+ } else { -+ __dump_instr(lvl, regs); -+ } - } - - #ifdef CONFIG_ARM_UNWIND -diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c -index 58fca9ad5fcc..3446b6fb3acb 100644 ---- a/arch/mips/ar7/platform.c -+++ b/arch/mips/ar7/platform.c -@@ -576,6 +576,7 @@ static int __init ar7_register_uarts(void) - uart_port.type = PORT_AR7; - uart_port.uartclk = clk_get_rate(bus_clk) / 2; - uart_port.iotype = UPIO_MEM32; -+ uart_port.flags = UPF_FIXED_TYPE; - uart_port.regshift = 2; - - uart_port.line = 0; -@@ -654,6 +655,10 @@ static int __init ar7_register_devices(void) - u32 val; - int res; - -+ res = ar7_gpio_init(); -+ if (res) -+ pr_warn("unable to register gpios: %d\n", res); -+ - res = ar7_register_uarts(); - if (res) - pr_err("unable to setup uart(s): %d\n", res); -diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c -index a23adc49d50f..36aabee9cba4 100644 ---- a/arch/mips/ar7/prom.c -+++ b/arch/mips/ar7/prom.c -@@ -246,8 +246,6 @@ void __init prom_init(void) - ar7_init_cmdline(fw_arg0, (char **)fw_arg1); - ar7_init_env((struct env_var *)fw_arg2); - console_config(); -- -- ar7_gpio_init(); - } - - #define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4))) -diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h -index 6516e9da5133..b836ddec82b7 100644 ---- a/arch/mips/include/asm/mips-cm.h -+++ b/arch/mips/include/asm/mips-cm.h -@@ -238,8 +238,8 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) - #define CM_GCR_BASE_GCRBASE_MSK (_ULCAST_(0x1ffff) << 15) - #define CM_GCR_BASE_CMDEFTGT_SHF 0 - #define CM_GCR_BASE_CMDEFTGT_MSK (_ULCAST_(0x3) << 0) --#define CM_GCR_BASE_CMDEFTGT_DISABLED 0 --#define CM_GCR_BASE_CMDEFTGT_MEM 1 -+#define CM_GCR_BASE_CMDEFTGT_MEM 0 -+#define CM_GCR_BASE_CMDEFTGT_RESERVED 1 - #define CM_GCR_BASE_CMDEFTGT_IOCU0 2 - #define CM_GCR_BASE_CMDEFTGT_IOCU1 3 - -diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c -index 477ba026c3e5..163b3449a8de 100644 ---- a/arch/mips/kernel/process.c -+++ b/arch/mips/kernel/process.c -@@ -49,9 +49,7 @@ - #ifdef CONFIG_HOTPLUG_CPU - void arch_cpu_idle_dead(void) - { -- /* What the heck is this check doing ? */ -- if (!cpumask_test_cpu(smp_processor_id(), &cpu_callin_map)) -- play_dead(); -+ play_dead(); - } - #endif - -diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c -index 7fef02a9eb85..4af08c197177 100644 ---- a/arch/mips/kernel/smp.c -+++ b/arch/mips/kernel/smp.c -@@ -64,6 +64,9 @@ EXPORT_SYMBOL(cpu_sibling_map); - cpumask_t cpu_core_map[NR_CPUS] __read_mostly; - EXPORT_SYMBOL(cpu_core_map); - -+static DECLARE_COMPLETION(cpu_starting); -+static DECLARE_COMPLETION(cpu_running); -+ - /* - * A logcal cpu mask containing only one VPE per core to - * reduce the number of IPIs on large MT systems. -@@ -174,9 +177,12 @@ asmlinkage void start_secondary(void) - cpumask_set_cpu(cpu, &cpu_coherent_mask); - notify_cpu_starting(cpu); - -- cpumask_set_cpu(cpu, &cpu_callin_map); -+ /* Notify boot CPU that we're starting & ready to sync counters */ -+ complete(&cpu_starting); -+ - synchronise_count_slave(cpu); - -+ /* The CPU is running and counters synchronised, now mark it online */ - set_cpu_online(cpu, true); - - set_cpu_sibling_map(cpu); -@@ -184,6 +190,12 @@ asmlinkage void start_secondary(void) - - calculate_cpu_foreign_map(); - -+ /* -+ * Notify boot CPU that we're up & online and it can safely return -+ * from __cpu_up -+ */ -+ complete(&cpu_running); -+ - /* - * irq will be enabled in ->smp_finish(), enabling it too early - * is dangerous. -@@ -242,22 +254,23 @@ void smp_prepare_boot_cpu(void) - { - set_cpu_possible(0, true); - set_cpu_online(0, true); -- cpumask_set_cpu(0, &cpu_callin_map); - } - - int __cpu_up(unsigned int cpu, struct task_struct *tidle) - { - mp_ops->boot_secondary(cpu, tidle); - -- /* -- * Trust is futile. We should really have timeouts ... -- */ -- while (!cpumask_test_cpu(cpu, &cpu_callin_map)) { -- udelay(100); -- schedule(); -+ /* Wait for CPU to start and be ready to sync counters */ -+ if (!wait_for_completion_timeout(&cpu_starting, -+ msecs_to_jiffies(1000))) { -+ pr_crit("CPU%u: failed to start\n", cpu); -+ return -EIO; - } - - synchronise_count_master(cpu); -+ -+ /* Wait for CPU to finish startup & mark itself online before return */ -+ wait_for_completion(&cpu_running); - return 0; - } - -diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c -index d78178daea4b..e2fe48dd67b5 100644 ---- a/arch/mips/mm/uasm-micromips.c -+++ b/arch/mips/mm/uasm-micromips.c -@@ -75,7 +75,7 @@ static struct insn insn_table_MM[] = { - { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, - { insn_lb, M(mm_lb32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, - { insn_ld, 0, 0 }, -- { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM }, -+ { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, - { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, - { insn_lld, 0, 0 }, - { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, -diff --git a/arch/powerpc/boot/dts/fsl/kmcoge4.dts b/arch/powerpc/boot/dts/fsl/kmcoge4.dts -index 6858ec9ef295..1a953d9edf1e 100644 ---- a/arch/powerpc/boot/dts/fsl/kmcoge4.dts -+++ b/arch/powerpc/boot/dts/fsl/kmcoge4.dts -@@ -83,6 +83,10 @@ - }; - }; - -+ sdhc@114000 { -+ status = "disabled"; -+ }; -+ - i2c@119000 { - status = "disabled"; - }; -diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c -index 24f58076d49e..1d2bc84338bf 100644 ---- a/arch/powerpc/kvm/book3s_hv_rm_xics.c -+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c -@@ -280,6 +280,7 @@ static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, - */ - if (reject && reject != XICS_IPI) { - arch_spin_unlock(&ics->lock); -+ icp->n_reject++; - new_irq = reject; - goto again; - } -@@ -611,10 +612,8 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) - state = &ics->irq_state[src]; - - /* Still asserted, resend it */ -- if (state->asserted) { -- icp->n_reject++; -+ if (state->asserted) - icp_rm_deliver_irq(xics, icp, irq); -- } - - if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) { - icp->rm_action |= XICS_RM_NOTIFY_EOI; -diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c -index 538c10db3537..8dc315b212c2 100644 ---- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c -+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c -@@ -165,7 +165,6 @@ static struct plat_sci_port scif2_platform_data = { - .scscr = SCSCR_TE | SCSCR_RE, - .type = PORT_IRDA, - .ops = &sh770x_sci_port_ops, -- .regshift = 1, - }; - - static struct resource scif2_resources[] = { -diff --git a/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S b/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S -index 85c4e1cf7172..e1693457c178 100644 ---- a/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S -+++ b/arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S -@@ -174,8 +174,8 @@ LABEL skip_ %I - .endr - - # Find min length -- vmovdqa _lens+0*16(state), %xmm0 -- vmovdqa _lens+1*16(state), %xmm1 -+ vmovdqu _lens+0*16(state), %xmm0 -+ vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} -@@ -195,8 +195,8 @@ LABEL skip_ %I - vpsubd %xmm2, %xmm0, %xmm0 - vpsubd %xmm2, %xmm1, %xmm1 - -- vmovdqa %xmm0, _lens+0*16(state) -- vmovdqa %xmm1, _lens+1*16(state) -+ vmovdqu %xmm0, _lens+0*16(state) -+ vmovdqu %xmm1, _lens+1*16(state) - - # "state" and "args" are the same address, arg1 - # len is arg2 -@@ -260,8 +260,8 @@ ENTRY(sha1_mb_mgr_get_comp_job_avx2) - jc .return_null - - # Find min length -- vmovdqa _lens(state), %xmm0 -- vmovdqa _lens+1*16(state), %xmm1 -+ vmovdqu _lens(state), %xmm0 -+ vmovdqu _lens+1*16(state), %xmm1 - - vpminud %xmm1, %xmm0, %xmm2 # xmm2 has {D,C,B,A} - vpalignr $8, %xmm2, %xmm3, %xmm3 # xmm3 has {x,x,D,C} -diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h -index b8c75f3aade8..d788b0cdc0ad 100644 ---- a/arch/x86/include/asm/uaccess.h -+++ b/arch/x86/include/asm/uaccess.h -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -66,6 +67,12 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un - __chk_range_not_ok((unsigned long __force)(addr), size, limit); \ - }) - -+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP -+# define WARN_ON_IN_IRQ() WARN_ON_ONCE(!in_task()) -+#else -+# define WARN_ON_IN_IRQ() -+#endif -+ - /** - * access_ok: - Checks if a user space pointer is valid - * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that -@@ -86,8 +93,11 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un - * checks that the pointer is in the user space range - after calling - * this function, memory access functions may still return -EFAULT. - */ --#define access_ok(type, addr, size) \ -- likely(!__range_not_ok(addr, size, user_addr_max())) -+#define access_ok(type, addr, size) \ -+({ \ -+ WARN_ON_IN_IRQ(); \ -+ likely(!__range_not_ok(addr, size, user_addr_max())); \ -+}) - - /* - * The exception table consists of pairs of addresses relative to the -diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c -index d90528ea5412..12c051d19e4b 100644 ---- a/arch/x86/oprofile/op_model_ppro.c -+++ b/arch/x86/oprofile/op_model_ppro.c -@@ -212,8 +212,8 @@ static void arch_perfmon_setup_counters(void) - eax.full = cpuid_eax(0xa); - - /* Workaround for BIOS bugs in 6/15. Taken from perfmon2 */ -- if (eax.split.version_id == 0 && __this_cpu_read(cpu_info.x86) == 6 && -- __this_cpu_read(cpu_info.x86_model) == 15) { -+ if (eax.split.version_id == 0 && boot_cpu_data.x86 == 6 && -+ boot_cpu_data.x86_model == 15) { - eax.split.version_id = 2; - eax.split.num_counters = 2; - eax.split.bit_width = 40; -diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c -index 2516e97c58f1..5e5a8adac0ba 100644 ---- a/crypto/asymmetric_keys/pkcs7_parser.c -+++ b/crypto/asymmetric_keys/pkcs7_parser.c -@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message); - static int pkcs7_check_authattrs(struct pkcs7_message *msg) - { - struct pkcs7_signed_info *sinfo; -- bool want; -+ bool want = false; - - sinfo = msg->signed_infos; - if (!sinfo) -diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c -index fbdddd6f94b8..ca3bcc81b623 100644 ---- a/drivers/block/rbd.c -+++ b/drivers/block/rbd.c -@@ -2736,7 +2736,7 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request) - * from the parent. - */ - page_count = (u32)calc_pages_for(0, length); -- pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); -+ pages = ceph_alloc_page_vector(page_count, GFP_NOIO); - if (IS_ERR(pages)) { - result = PTR_ERR(pages); - pages = NULL; -@@ -2863,7 +2863,7 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request) - */ - size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32); - page_count = (u32)calc_pages_for(0, size); -- pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); -+ pages = ceph_alloc_page_vector(page_count, GFP_NOIO); - if (IS_ERR(pages)) - return PTR_ERR(pages); - -diff --git a/drivers/crypto/vmx/aes_ctr.c b/drivers/crypto/vmx/aes_ctr.c -index 72f138985e18..d83ab4bac8b1 100644 ---- a/drivers/crypto/vmx/aes_ctr.c -+++ b/drivers/crypto/vmx/aes_ctr.c -@@ -80,11 +80,13 @@ static int p8_aes_ctr_setkey(struct crypto_tfm *tfm, const u8 *key, - int ret; - struct p8_aes_ctr_ctx *ctx = crypto_tfm_ctx(tfm); - -+ preempt_disable(); - pagefault_disable(); - enable_kernel_altivec(); - enable_kernel_vsx(); - ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key); - pagefault_enable(); -+ preempt_enable(); - - ret += crypto_blkcipher_setkey(ctx->fallback, key, keylen); - return ret; -@@ -99,11 +101,13 @@ static void p8_aes_ctr_final(struct p8_aes_ctr_ctx *ctx, - u8 *dst = walk->dst.virt.addr; - unsigned int nbytes = walk->nbytes; - -+ preempt_disable(); - pagefault_disable(); - enable_kernel_altivec(); - enable_kernel_vsx(); - aes_p8_encrypt(ctrblk, keystream, &ctx->enc_key); - pagefault_enable(); -+ preempt_enable(); - - crypto_xor(keystream, src, nbytes); - memcpy(dst, keystream, nbytes); -@@ -132,6 +136,7 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc, - blkcipher_walk_init(&walk, dst, src, nbytes); - ret = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE); - while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) { -+ preempt_disable(); - pagefault_disable(); - enable_kernel_altivec(); - enable_kernel_vsx(); -@@ -143,6 +148,7 @@ static int p8_aes_ctr_crypt(struct blkcipher_desc *desc, - &ctx->enc_key, - walk.iv); - pagefault_enable(); -+ preempt_enable(); - - /* We need to update IV mostly for last bytes/round */ - inc = (nbytes & AES_BLOCK_MASK) / AES_BLOCK_SIZE; -diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c -index 7dd6728dd092..ccc2044af831 100644 ---- a/drivers/gpu/drm/drm_drv.c -+++ b/drivers/gpu/drm/drm_drv.c -@@ -312,7 +312,7 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type) - ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root); - if (ret) { - DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); -- return ret; -+ goto err_debugfs; - } - - ret = device_add(minor->kdev); -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c -index f3f31f995878..be3971b22a02 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c -@@ -708,7 +708,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) - * allocation taken by fbdev - */ - if (!(dev_priv->capabilities & SVGA_CAP_3D)) -- mem_size *= 2; -+ mem_size *= 3; - - dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE; - dev_priv->prim_bb_mem = -diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c -index 572bc6f02ca8..e18f12b74610 100644 ---- a/drivers/iio/trigger/iio-trig-interrupt.c -+++ b/drivers/iio/trigger/iio-trig-interrupt.c -@@ -58,7 +58,7 @@ static int iio_interrupt_trigger_probe(struct platform_device *pdev) - trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); - if (!trig_info) { - ret = -ENOMEM; -- goto error_put_trigger; -+ goto error_free_trigger; - } - iio_trigger_set_drvdata(trig, trig_info); - trig_info->irq = irq; -@@ -83,8 +83,8 @@ error_release_irq: - free_irq(irq, trig); - error_free_trig_info: - kfree(trig_info); --error_put_trigger: -- iio_trigger_put(trig); -+error_free_trigger: -+ iio_trigger_free(trig); - error_ret: - return ret; - } -@@ -99,7 +99,7 @@ static int iio_interrupt_trigger_remove(struct platform_device *pdev) - iio_trigger_unregister(trig); - free_irq(trig_info->irq, trig); - kfree(trig_info); -- iio_trigger_put(trig); -+ iio_trigger_free(trig); - - return 0; - } -diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c -index 3dfab2bc6d69..202e8b89caf2 100644 ---- a/drivers/iio/trigger/iio-trig-sysfs.c -+++ b/drivers/iio/trigger/iio-trig-sysfs.c -@@ -174,7 +174,7 @@ static int iio_sysfs_trigger_probe(int id) - return 0; - - out2: -- iio_trigger_put(t->trig); -+ iio_trigger_free(t->trig); - free_t: - kfree(t); - out1: -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c -index 2018d24344de..f74b11542603 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c -@@ -1373,7 +1373,7 @@ static void ipoib_cm_tx_reap(struct work_struct *work) - - while (!list_empty(&priv->cm.reap_list)) { - p = list_entry(priv->cm.reap_list.next, typeof(*p), list); -- list_del(&p->list); -+ list_del_init(&p->list); - spin_unlock_irqrestore(&priv->lock, flags); - netif_tx_unlock_bh(dev); - ipoib_cm_tx_destroy(p); -diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c -index 0fd612dd76ed..aaf43befffaa 100644 ---- a/drivers/input/keyboard/mpr121_touchkey.c -+++ b/drivers/input/keyboard/mpr121_touchkey.c -@@ -87,7 +87,8 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) - struct mpr121_touchkey *mpr121 = dev_id; - struct i2c_client *client = mpr121->client; - struct input_dev *input = mpr121->input_dev; -- unsigned int key_num, key_val, pressed; -+ unsigned long bit_changed; -+ unsigned int key_num; - int reg; - - reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR); -@@ -105,18 +106,22 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id) - - reg &= TOUCH_STATUS_MASK; - /* use old press bit to figure out which bit changed */ -- key_num = ffs(reg ^ mpr121->statusbits) - 1; -- pressed = reg & (1 << key_num); -+ bit_changed = reg ^ mpr121->statusbits; - mpr121->statusbits = reg; -+ for_each_set_bit(key_num, &bit_changed, mpr121->keycount) { -+ unsigned int key_val, pressed; - -- key_val = mpr121->keycodes[key_num]; -+ pressed = reg & BIT(key_num); -+ key_val = mpr121->keycodes[key_num]; - -- input_event(input, EV_MSC, MSC_SCAN, key_num); -- input_report_key(input, key_val, pressed); -- input_sync(input); -+ input_event(input, EV_MSC, MSC_SCAN, key_num); -+ input_report_key(input, key_val, pressed); -+ -+ dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, -+ pressed ? "pressed" : "released"); - -- dev_dbg(&client->dev, "key %d %d %s\n", key_num, key_val, -- pressed ? "pressed" : "released"); -+ } -+ input_sync(input); - - out: - return IRQ_HANDLED; -@@ -231,6 +236,7 @@ static int mpr_touchkey_probe(struct i2c_client *client, - input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); -+ input_set_capability(input_dev, EV_MSC, MSC_SCAN); - - input_dev->keycode = mpr121->keycodes; - input_dev->keycodesize = sizeof(mpr121->keycodes[0]); -diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c -index b8c50d883b2c..c9d491bc85e0 100644 ---- a/drivers/input/mouse/elan_i2c_core.c -+++ b/drivers/input/mouse/elan_i2c_core.c -@@ -1240,6 +1240,7 @@ static const struct acpi_device_id elan_acpi_id[] = { - { "ELAN0605", 0 }, - { "ELAN0609", 0 }, - { "ELAN060B", 0 }, -+ { "ELAN060C", 0 }, - { "ELAN0611", 0 }, - { "ELAN1000", 0 }, - { } -diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c -index 00df3832faab..64f1eb8fdcbc 100644 ---- a/drivers/iommu/arm-smmu-v3.c -+++ b/drivers/iommu/arm-smmu-v3.c -@@ -1033,13 +1033,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, - } - } - -- /* Nuke the existing Config, as we're going to rewrite it */ -- val &= ~(STRTAB_STE_0_CFG_MASK << STRTAB_STE_0_CFG_SHIFT); -- -- if (ste->valid) -- val |= STRTAB_STE_0_V; -- else -- val &= ~STRTAB_STE_0_V; -+ /* Nuke the existing STE_0 value, as we're going to rewrite it */ -+ val = ste->valid ? STRTAB_STE_0_V : 0; - - if (ste->bypass) { - val |= disable_bypass ? STRTAB_STE_0_CFG_ABORT -@@ -1068,7 +1063,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, - val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK - << STRTAB_STE_0_S1CTXPTR_SHIFT) | - STRTAB_STE_0_CFG_S1_TRANS; -- - } - - if (ste->s2_cfg) { -diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c -index 01adcdc52346..a9e2722f5e22 100644 ---- a/drivers/media/i2c/adv7604.c -+++ b/drivers/media/i2c/adv7604.c -@@ -2856,6 +2856,9 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) - state->pdata.alt_data_sat = 1; - state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0; - state->pdata.bus_order = ADV7604_BUS_ORDER_RGB; -+ state->pdata.dr_str_data = ADV76XX_DR_STR_MEDIUM_HIGH; -+ state->pdata.dr_str_clk = ADV76XX_DR_STR_MEDIUM_HIGH; -+ state->pdata.dr_str_sync = ADV76XX_DR_STR_MEDIUM_HIGH; - - return 0; - } -diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c -index cf7c18947189..d065c0e2d18e 100644 ---- a/drivers/net/can/c_can/c_can_pci.c -+++ b/drivers/net/can/c_can/c_can_pci.c -@@ -178,7 +178,6 @@ static int c_can_pci_probe(struct pci_dev *pdev, - break; - case BOSCH_D_CAN: - priv->regs = reg_map_d_can; -- priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; - break; - default: - ret = -EINVAL; -diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c -index e36d10520e24..717530eac70c 100644 ---- a/drivers/net/can/c_can/c_can_platform.c -+++ b/drivers/net/can/c_can/c_can_platform.c -@@ -320,7 +320,6 @@ static int c_can_plat_probe(struct platform_device *pdev) - break; - case BOSCH_D_CAN: - priv->regs = reg_map_d_can; -- priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; - priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; - priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; - priv->read_reg32 = d_can_plat_read_reg32; -diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c -index b0c80859f746..1ac2090a1721 100644 ---- a/drivers/net/can/sun4i_can.c -+++ b/drivers/net/can/sun4i_can.c -@@ -539,6 +539,13 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) - } - stats->rx_over_errors++; - stats->rx_errors++; -+ -+ /* reset the CAN IP by entering reset mode -+ * ignoring timeout error -+ */ -+ set_reset_mode(dev); -+ set_normal_mode(dev); -+ - /* clear bit */ - sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG); - } -@@ -653,8 +660,9 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id) - netif_wake_queue(dev); - can_led_event(dev, CAN_LED_EVENT_TX); - } -- if (isrc & SUN4I_INT_RBUF_VLD) { -- /* receive interrupt */ -+ if ((isrc & SUN4I_INT_RBUF_VLD) && -+ !(isrc & SUN4I_INT_DATA_OR)) { -+ /* receive interrupt - don't read if overrun occurred */ - while (status & SUN4I_STA_RBUF_RDY) { - /* RX buffer is not empty */ - sun4i_can_rx(dev); -diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c -index e0e94b855bbe..1228d0da4075 100644 ---- a/drivers/net/usb/cdc_ncm.c -+++ b/drivers/net/usb/cdc_ncm.c -@@ -724,8 +724,10 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ - u8 *buf; - int len; - int temp; -+ int err; - u8 iface_no; - struct usb_cdc_parsed_header hdr; -+ u16 curr_ntb_format; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) -@@ -823,6 +825,32 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ - goto error2; - } - -+ /* -+ * Some Huawei devices have been observed to come out of reset in NDP32 mode. -+ * Let's check if this is the case, and set the device to NDP16 mode again if -+ * needed. -+ */ -+ if (ctx->drvflags & CDC_NCM_FLAG_RESET_NTB16) { -+ err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_FORMAT, -+ USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, -+ 0, iface_no, &curr_ntb_format, 2); -+ if (err < 0) { -+ goto error2; -+ } -+ -+ if (curr_ntb_format == USB_CDC_NCM_NTB32_FORMAT) { -+ dev_info(&intf->dev, "resetting NTB format to 16-bit"); -+ err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT, -+ USB_TYPE_CLASS | USB_DIR_OUT -+ | USB_RECIP_INTERFACE, -+ USB_CDC_NCM_NTB16_FORMAT, -+ iface_no, NULL, 0); -+ -+ if (err < 0) -+ goto error2; -+ } -+ } -+ - cdc_ncm_find_endpoints(dev, ctx->data); - cdc_ncm_find_endpoints(dev, ctx->control); - if (!dev->in || !dev->out || !dev->status) { -diff --git a/drivers/net/usb/huawei_cdc_ncm.c b/drivers/net/usb/huawei_cdc_ncm.c -index 2680a65cd5e4..63f28908afda 100644 ---- a/drivers/net/usb/huawei_cdc_ncm.c -+++ b/drivers/net/usb/huawei_cdc_ncm.c -@@ -80,6 +80,12 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev, - * be at the end of the frame. - */ - drvflags |= CDC_NCM_FLAG_NDP_TO_END; -+ -+ /* Additionally, it has been reported that some Huawei E3372H devices, with -+ * firmware version 21.318.01.00.541, come out of reset in NTB32 format mode, hence -+ * needing to be set to the NTB16 one again. -+ */ -+ drvflags |= CDC_NCM_FLAG_RESET_NTB16; - ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags); - if (ret) - goto err; -diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c -index 72ee1c305cc4..02db20b26749 100644 ---- a/drivers/net/xen-netback/netback.c -+++ b/drivers/net/xen-netback/netback.c -@@ -67,6 +67,7 @@ module_param(rx_drain_timeout_msecs, uint, 0444); - unsigned int rx_stall_timeout_msecs = 60000; - module_param(rx_stall_timeout_msecs, uint, 0444); - -+#define MAX_QUEUES_DEFAULT 8 - unsigned int xenvif_max_queues; - module_param_named(max_queues, xenvif_max_queues, uint, 0644); - MODULE_PARM_DESC(max_queues, -@@ -2157,11 +2158,12 @@ static int __init netback_init(void) - if (!xen_domain()) - return -ENODEV; - -- /* Allow as many queues as there are CPUs if user has not -+ /* Allow as many queues as there are CPUs but max. 8 if user has not - * specified a value. - */ - if (xenvif_max_queues == 0) -- xenvif_max_queues = num_online_cpus(); -+ xenvif_max_queues = min_t(unsigned int, MAX_QUEUES_DEFAULT, -+ num_online_cpus()); - - if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) { - pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", -diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c -index 53b79c5f0559..379d08f76146 100644 ---- a/drivers/pci/host/pci-mvebu.c -+++ b/drivers/pci/host/pci-mvebu.c -@@ -131,6 +131,12 @@ struct mvebu_pcie { - int nports; - }; - -+struct mvebu_pcie_window { -+ phys_addr_t base; -+ phys_addr_t remap; -+ size_t size; -+}; -+ - /* Structure representing one PCIe interface */ - struct mvebu_pcie_port { - char *name; -@@ -148,10 +154,8 @@ struct mvebu_pcie_port { - struct mvebu_sw_pci_bridge bridge; - struct device_node *dn; - struct mvebu_pcie *pcie; -- phys_addr_t memwin_base; -- size_t memwin_size; -- phys_addr_t iowin_base; -- size_t iowin_size; -+ struct mvebu_pcie_window memwin; -+ struct mvebu_pcie_window iowin; - u32 saved_pcie_stat; - }; - -@@ -377,23 +381,45 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, - } - } - -+static void mvebu_pcie_set_window(struct mvebu_pcie_port *port, -+ unsigned int target, unsigned int attribute, -+ const struct mvebu_pcie_window *desired, -+ struct mvebu_pcie_window *cur) -+{ -+ if (desired->base == cur->base && desired->remap == cur->remap && -+ desired->size == cur->size) -+ return; -+ -+ if (cur->size != 0) { -+ mvebu_pcie_del_windows(port, cur->base, cur->size); -+ cur->size = 0; -+ cur->base = 0; -+ -+ /* -+ * If something tries to change the window while it is enabled -+ * the change will not be done atomically. That would be -+ * difficult to do in the general case. -+ */ -+ } -+ -+ if (desired->size == 0) -+ return; -+ -+ mvebu_pcie_add_windows(port, target, attribute, desired->base, -+ desired->size, desired->remap); -+ *cur = *desired; -+} -+ - static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) - { -- phys_addr_t iobase; -+ struct mvebu_pcie_window desired = {}; - - /* Are the new iobase/iolimit values invalid? */ - if (port->bridge.iolimit < port->bridge.iobase || - port->bridge.iolimitupper < port->bridge.iobaseupper || - !(port->bridge.command & PCI_COMMAND_IO)) { -- -- /* If a window was configured, remove it */ -- if (port->iowin_base) { -- mvebu_pcie_del_windows(port, port->iowin_base, -- port->iowin_size); -- port->iowin_base = 0; -- port->iowin_size = 0; -- } -- -+ mvebu_pcie_set_window(port, port->io_target, port->io_attr, -+ &desired, &port->iowin); - return; - } - -@@ -410,32 +436,27 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) - * specifications. iobase is the bus address, port->iowin_base - * is the CPU address. - */ -- iobase = ((port->bridge.iobase & 0xF0) << 8) | -- (port->bridge.iobaseupper << 16); -- port->iowin_base = port->pcie->io.start + iobase; -- port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | -- (port->bridge.iolimitupper << 16)) - -- iobase) + 1; -- -- mvebu_pcie_add_windows(port, port->io_target, port->io_attr, -- port->iowin_base, port->iowin_size, -- iobase); -+ desired.remap = ((port->bridge.iobase & 0xF0) << 8) | -+ (port->bridge.iobaseupper << 16); -+ desired.base = port->pcie->io.start + desired.remap; -+ desired.size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | -+ (port->bridge.iolimitupper << 16)) - -+ desired.remap) + -+ 1; -+ -+ mvebu_pcie_set_window(port, port->io_target, port->io_attr, &desired, -+ &port->iowin); - } - - static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) - { -+ struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP}; -+ - /* Are the new membase/memlimit values invalid? */ - if (port->bridge.memlimit < port->bridge.membase || - !(port->bridge.command & PCI_COMMAND_MEMORY)) { -- -- /* If a window was configured, remove it */ -- if (port->memwin_base) { -- mvebu_pcie_del_windows(port, port->memwin_base, -- port->memwin_size); -- port->memwin_base = 0; -- port->memwin_size = 0; -- } -- -+ mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, -+ &desired, &port->memwin); - return; - } - -@@ -445,14 +466,12 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) - * window to setup, according to the PCI-to-PCI bridge - * specifications. - */ -- port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); -- port->memwin_size = -- (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - -- port->memwin_base + 1; -- -- mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, -- port->memwin_base, port->memwin_size, -- MVEBU_MBUS_NO_REMAP); -+ desired.base = ((port->bridge.membase & 0xFFF0) << 16); -+ desired.size = (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - -+ desired.base + 1; -+ -+ mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, &desired, -+ &port->memwin); - } - - /* -diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c -index af2046c87806..847f75601591 100644 ---- a/drivers/platform/x86/hp-wmi.c -+++ b/drivers/platform/x86/hp-wmi.c -@@ -249,7 +249,7 @@ static int hp_wmi_display_state(void) - int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, - sizeof(state), sizeof(state)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return state; - } - -@@ -259,7 +259,7 @@ static int hp_wmi_hddtemp_state(void) - int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, - sizeof(state), sizeof(state)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return state; - } - -@@ -269,7 +269,7 @@ static int hp_wmi_als_state(void) - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, - sizeof(state), sizeof(state)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return state; - } - -@@ -280,7 +280,7 @@ static int hp_wmi_dock_state(void) - sizeof(state), sizeof(state)); - - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - - return state & 0x1; - } -@@ -291,7 +291,7 @@ static int hp_wmi_tablet_state(void) - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, - sizeof(state), sizeof(state)); - if (ret) -- return ret; -+ return ret < 0 ? ret : -EINVAL; - - return (state & 0x4) ? 1 : 0; - } -@@ -324,7 +324,7 @@ static int __init hp_wmi_enable_hotkeys(void) - int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value, - sizeof(value), 0); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return 0; - } - -@@ -337,7 +337,7 @@ static int hp_wmi_set_block(void *data, bool blocked) - ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, - &query, sizeof(query), 0); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return 0; - } - -@@ -429,7 +429,7 @@ static int hp_wmi_post_code_state(void) - int ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 0, &state, - sizeof(state), sizeof(state)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - return state; - } - -@@ -495,7 +495,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr, - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, - sizeof(tmp), sizeof(tmp)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - - return count; - } -@@ -516,7 +516,7 @@ static ssize_t set_postcode(struct device *dev, struct device_attribute *attr, - ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 1, &tmp, - sizeof(tmp), sizeof(tmp)); - if (ret) -- return -EINVAL; -+ return ret < 0 ? ret : -EINVAL; - - return count; - } -@@ -573,10 +573,12 @@ static void hp_wmi_notify(u32 value, void *context) - - switch (event_id) { - case HPWMI_DOCK_EVENT: -- input_report_switch(hp_wmi_input_dev, SW_DOCK, -- hp_wmi_dock_state()); -- input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, -- hp_wmi_tablet_state()); -+ if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) -+ input_report_switch(hp_wmi_input_dev, SW_DOCK, -+ hp_wmi_dock_state()); -+ if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) -+ input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, -+ hp_wmi_tablet_state()); - input_sync(hp_wmi_input_dev); - break; - case HPWMI_PARK_HDD: -@@ -649,6 +651,7 @@ static int __init hp_wmi_input_setup(void) - { - acpi_status status; - int err; -+ int val; - - hp_wmi_input_dev = input_allocate_device(); - if (!hp_wmi_input_dev) -@@ -659,17 +662,26 @@ static int __init hp_wmi_input_setup(void) - hp_wmi_input_dev->id.bustype = BUS_HOST; - - __set_bit(EV_SW, hp_wmi_input_dev->evbit); -- __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); -- __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); -+ -+ /* Dock */ -+ val = hp_wmi_dock_state(); -+ if (!(val < 0)) { -+ __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); -+ input_report_switch(hp_wmi_input_dev, SW_DOCK, val); -+ } -+ -+ /* Tablet mode */ -+ val = hp_wmi_tablet_state(); -+ if (!(val < 0)) { -+ __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); -+ input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); -+ } - - err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); - if (err) - goto err_free_dev; - - /* Set initial hardware state */ -- input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); -- input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, -- hp_wmi_tablet_state()); - input_sync(hp_wmi_input_dev); - - if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later()) -@@ -982,10 +994,12 @@ static int hp_wmi_resume_handler(struct device *device) - * changed. - */ - if (hp_wmi_input_dev) { -- input_report_switch(hp_wmi_input_dev, SW_DOCK, -- hp_wmi_dock_state()); -- input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, -- hp_wmi_tablet_state()); -+ if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) -+ input_report_switch(hp_wmi_input_dev, SW_DOCK, -+ hp_wmi_dock_state()); -+ if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) -+ input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, -+ hp_wmi_tablet_state()); - input_sync(hp_wmi_input_dev); - } - -diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h -index 741f3ee81cfe..5006cb6ce62d 100644 ---- a/drivers/s390/net/qeth_core.h -+++ b/drivers/s390/net/qeth_core.h -@@ -909,7 +909,6 @@ void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long); - int qeth_core_hardsetup_card(struct qeth_card *); - void qeth_print_status_message(struct qeth_card *); - int qeth_init_qdio_queues(struct qeth_card *); --int qeth_send_startlan(struct qeth_card *); - int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, - int (*reply_cb) - (struct qeth_card *, struct qeth_reply *, unsigned long), -diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c -index d10bf3da8e5f..e5b9506698b1 100644 ---- a/drivers/s390/net/qeth_core_main.c -+++ b/drivers/s390/net/qeth_core_main.c -@@ -2955,7 +2955,7 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, - } - EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); - --int qeth_send_startlan(struct qeth_card *card) -+static int qeth_send_startlan(struct qeth_card *card) - { - int rc; - struct qeth_cmd_buffer *iob; -@@ -2968,7 +2968,6 @@ int qeth_send_startlan(struct qeth_card *card) - rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); - return rc; - } --EXPORT_SYMBOL_GPL(qeth_send_startlan); - - static int qeth_default_setadapterparms_cb(struct qeth_card *card, - struct qeth_reply *reply, unsigned long data) -@@ -5080,6 +5079,20 @@ retriable: - goto out; - } - -+ rc = qeth_send_startlan(card); -+ if (rc) { -+ QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); -+ if (rc == IPA_RC_LAN_OFFLINE) { -+ dev_warn(&card->gdev->dev, -+ "The LAN is offline\n"); -+ card->lan_online = 0; -+ } else { -+ rc = -ENODEV; -+ goto out; -+ } -+ } else -+ card->lan_online = 1; -+ - card->options.ipa4.supported_funcs = 0; - card->options.ipa6.supported_funcs = 0; - card->options.adp.supported_funcs = 0; -@@ -5091,14 +5104,14 @@ retriable: - if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { - rc = qeth_query_setadapterparms(card); - if (rc < 0) { -- QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); -+ QETH_DBF_TEXT_(SETUP, 2, "7err%d", rc); - goto out; - } - } - if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) { - rc = qeth_query_setdiagass(card); - if (rc < 0) { -- QETH_DBF_TEXT_(SETUP, 2, "7err%d", rc); -+ QETH_DBF_TEXT_(SETUP, 2, "8err%d", rc); - goto out; - } - } -diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c -index bf1e0e39334d..58bcb3c9a86a 100644 ---- a/drivers/s390/net/qeth_l2_main.c -+++ b/drivers/s390/net/qeth_l2_main.c -@@ -1203,21 +1203,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) - /* softsetup */ - QETH_DBF_TEXT(SETUP, 2, "softsetp"); - -- rc = qeth_send_startlan(card); -- if (rc) { -- QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); -- if (rc == 0xe080) { -- dev_warn(&card->gdev->dev, -- "The LAN is offline\n"); -- card->lan_online = 0; -- goto contin; -- } -- rc = -ENODEV; -- goto out_remove; -- } else -- card->lan_online = 1; -- --contin: - if ((card->info.type == QETH_CARD_TYPE_OSD) || - (card->info.type == QETH_CARD_TYPE_OSX)) { - if (qeth_l2_start_ipassists(card)) -diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c -index 285fe0b2c753..bf3c1b2301db 100644 ---- a/drivers/s390/net/qeth_l3_main.c -+++ b/drivers/s390/net/qeth_l3_main.c -@@ -3298,21 +3298,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) - /* softsetup */ - QETH_DBF_TEXT(SETUP, 2, "softsetp"); - -- rc = qeth_send_startlan(card); -- if (rc) { -- QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); -- if (rc == 0xe080) { -- dev_warn(&card->gdev->dev, -- "The LAN is offline\n"); -- card->lan_online = 0; -- goto contin; -- } -- rc = -ENODEV; -- goto out_remove; -- } else -- card->lan_online = 1; -- --contin: - rc = qeth_l3_setadapter_parms(card); - if (rc) - QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc); -diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c -index 035dd456d7d6..737747354db6 100644 ---- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c -+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c -@@ -259,7 +259,7 @@ out_free_irq: - out1: - iio_trigger_unregister(st->trig); - out: -- iio_trigger_put(st->trig); -+ iio_trigger_free(st->trig); - return ret; - } - -@@ -272,7 +272,7 @@ static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) - peripheral_free(st->t->pin); - free_irq(st->irq, st); - iio_trigger_unregister(st->trig); -- iio_trigger_put(st->trig); -+ iio_trigger_free(st->trig); - - return 0; - } -diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c -index 235e150d7b81..80d0ffe7abc1 100644 ---- a/drivers/tty/serial/sh-sci.c -+++ b/drivers/tty/serial/sh-sci.c -@@ -163,18 +163,17 @@ static const struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = { - }, - - /* -- * Common definitions for legacy IrDA ports, dependent on -- * regshift value. -+ * Common definitions for legacy IrDA ports. - */ - [SCIx_IRDA_REGTYPE] = { - [SCSMR] = { 0x00, 8 }, -- [SCBRR] = { 0x01, 8 }, -- [SCSCR] = { 0x02, 8 }, -- [SCxTDR] = { 0x03, 8 }, -- [SCxSR] = { 0x04, 8 }, -- [SCxRDR] = { 0x05, 8 }, -- [SCFCR] = { 0x06, 8 }, -- [SCFDR] = { 0x07, 16 }, -+ [SCBRR] = { 0x02, 8 }, -+ [SCSCR] = { 0x04, 8 }, -+ [SCxTDR] = { 0x06, 8 }, -+ [SCxSR] = { 0x08, 16 }, -+ [SCxRDR] = { 0x0a, 8 }, -+ [SCFCR] = { 0x0c, 8 }, -+ [SCFDR] = { 0x0e, 16 }, - [SCTFDR] = sci_reg_invalid, - [SCRFDR] = sci_reg_invalid, - [SCSPTR] = sci_reg_invalid, -diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c -index 5c0952995280..87a83d925eea 100644 ---- a/drivers/usb/core/hcd.c -+++ b/drivers/usb/core/hcd.c -@@ -2997,6 +2997,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) - } - - usb_put_invalidate_rhdev(hcd); -+ hcd->flags = 0; - } - EXPORT_SYMBOL_GPL(usb_remove_hcd); - -diff --git a/drivers/video/fbdev/pmag-ba-fb.c b/drivers/video/fbdev/pmag-ba-fb.c -index 914a52ba8477..77837665ce89 100644 ---- a/drivers/video/fbdev/pmag-ba-fb.c -+++ b/drivers/video/fbdev/pmag-ba-fb.c -@@ -129,7 +129,7 @@ static struct fb_ops pmagbafb_ops = { - /* - * Turn the hardware cursor off. - */ --static void __init pmagbafb_erase_cursor(struct fb_info *info) -+static void pmagbafb_erase_cursor(struct fb_info *info) - { - struct pmagbafb_par *par = info->par; - -diff --git a/include/linux/phy.h b/include/linux/phy.h -index b64825d6ad26..5bc4b9d563a9 100644 ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -136,11 +136,7 @@ static inline const char *phy_modes(phy_interface_t interface) - /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ - #define PHY_ID_FMT "%s:%02x" - --/* -- * Need to be a little smaller than phydev->dev.bus_id to leave room -- * for the ":%02x" -- */ --#define MII_BUS_ID_SIZE (20 - 3) -+#define MII_BUS_ID_SIZE 61 - - /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit - IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */ -@@ -599,7 +595,7 @@ struct phy_driver { - /* A Structure for boards to register fixups with the PHY Lib */ - struct phy_fixup { - struct list_head list; -- char bus_id[20]; -+ char bus_id[MII_BUS_ID_SIZE + 3]; - u32 phy_uid; - u32 phy_uid_mask; - int (*run)(struct phy_device *phydev); -diff --git a/include/linux/preempt.h b/include/linux/preempt.h -index 75e4e30677f1..7eeceac52dea 100644 ---- a/include/linux/preempt.h -+++ b/include/linux/preempt.h -@@ -65,19 +65,24 @@ - - /* - * Are we doing bottom half or hardware interrupt processing? -- * Are we in a softirq context? Interrupt context? -- * in_softirq - Are we currently processing softirq or have bh disabled? -- * in_serving_softirq - Are we currently processing softirq? -+ * -+ * in_irq() - We're in (hard) IRQ context -+ * in_softirq() - We have BH disabled, or are processing softirqs -+ * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled -+ * in_serving_softirq() - We're in softirq context -+ * in_nmi() - We're in NMI context -+ * in_task() - We're in task context -+ * -+ * Note: due to the BH disabled confusion: in_softirq(),in_interrupt() really -+ * should not be used in new code. - */ - #define in_irq() (hardirq_count()) - #define in_softirq() (softirq_count()) - #define in_interrupt() (irq_count()) - #define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET) -- --/* -- * Are we in NMI context? -- */ --#define in_nmi() (preempt_count() & NMI_MASK) -+#define in_nmi() (preempt_count() & NMI_MASK) -+#define in_task() (!(preempt_count() & \ -+ (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET))) - - /* - * The preempt_count offset after preempt_disable(); -diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h -index 3a375d07d0dc..6670e9b34f20 100644 ---- a/include/linux/usb/cdc_ncm.h -+++ b/include/linux/usb/cdc_ncm.h -@@ -82,6 +82,7 @@ - - /* Driver flags */ - #define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */ -+#define CDC_NCM_FLAG_RESET_NTB16 0x08 /* set NDP16 one more time after altsetting switch */ - - #define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \ - (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE) -diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h -index feb58d455560..4b9ee3009aa0 100644 ---- a/include/sound/seq_kernel.h -+++ b/include/sound/seq_kernel.h -@@ -49,7 +49,8 @@ typedef union snd_seq_timestamp snd_seq_timestamp_t; - #define SNDRV_SEQ_DEFAULT_CLIENT_EVENTS 200 - - /* max delivery path length */ --#define SNDRV_SEQ_MAX_HOPS 10 -+/* NOTE: this shouldn't be greater than MAX_LOCKDEP_SUBCLASSES */ -+#define SNDRV_SEQ_MAX_HOPS 8 - - /* max size of event size */ - #define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff -diff --git a/kernel/workqueue_internal.h b/kernel/workqueue_internal.h -index 45215870ac6c..3fa9c146fccb 100644 ---- a/kernel/workqueue_internal.h -+++ b/kernel/workqueue_internal.h -@@ -9,6 +9,7 @@ - - #include - #include -+#include - - struct worker_pool; - -@@ -59,7 +60,7 @@ struct worker { - */ - static inline struct worker *current_wq_worker(void) - { -- if (current->flags & PF_WQ_WORKER) -+ if (in_task() && (current->flags & PF_WQ_WORKER)) - return kthread_data(current); - return NULL; - } -diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c -index faa2a3f017f8..4fa2e54b3f59 100644 ---- a/lib/asn1_decoder.c -+++ b/lib/asn1_decoder.c -@@ -227,7 +227,7 @@ next_op: - hdr = 2; - - /* Extract a tag from the data */ -- if (unlikely(dp >= datalen - 1)) -+ if (unlikely(datalen - dp < 2)) - goto data_overrun_error; - tag = data[dp++]; - if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) -@@ -273,7 +273,7 @@ next_op: - int n = len - 0x80; - if (unlikely(n > 2)) - goto length_too_long; -- if (unlikely(dp >= datalen - n)) -+ if (unlikely(n > datalen - dp)) - goto data_overrun_error; - hdr += n; - for (len = 0; n > 0; n--) { -diff --git a/lib/test_firmware.c b/lib/test_firmware.c -index 86374c1c49a4..841191061816 100644 ---- a/lib/test_firmware.c -+++ b/lib/test_firmware.c -@@ -65,14 +65,19 @@ static ssize_t trigger_request_store(struct device *dev, - release_firmware(test_firmware); - test_firmware = NULL; - rc = request_firmware(&test_firmware, name, dev); -- if (rc) -+ if (rc) { - pr_info("load of '%s' failed: %d\n", name, rc); -- pr_info("loaded: %zu\n", test_firmware ? test_firmware->size : 0); -+ goto out; -+ } -+ pr_info("loaded: %zu\n", test_firmware->size); -+ rc = count; -+ -+out: - mutex_unlock(&test_fw_mutex); - - kfree(name); - -- return count; -+ return rc; - } - static DEVICE_ATTR_WO(trigger_request); - -diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig -index ff7736f7ff42..fc0c09e770e6 100644 ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -1,12 +1,13 @@ - config HAVE_NET_DSA - def_bool y -- depends on NETDEVICES && !S390 -+ depends on INET && NETDEVICES && !S390 - - # Drivers must select NET_DSA and the appropriate tagging format - - config NET_DSA - tristate "Distributed Switch Architecture" -- depends on HAVE_NET_DSA && NET_SWITCHDEV -+ depends on HAVE_NET_DSA -+ select NET_SWITCHDEV - select PHYLIB - ---help--- - Say Y if you want to enable support for the hardware switches supported -diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c -index f2a71025a770..22377c8ff14b 100644 ---- a/net/ipv4/ah4.c -+++ b/net/ipv4/ah4.c -@@ -270,6 +270,9 @@ static void ah_input_done(struct crypto_async_request *base, int err) - int ihl = ip_hdrlen(skb); - int ah_hlen = (ah->hdrlen + 2) << 2; - -+ if (err) -+ goto out; -+ - work_iph = AH_SKB_CB(skb)->tmp; - auth_data = ah_tmp_auth(work_iph, ihl); - icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); -diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c -index 9dfaf4d55ee0..a97a5bf716be 100644 ---- a/net/netfilter/nft_meta.c -+++ b/net/netfilter/nft_meta.c -@@ -151,8 +151,34 @@ void nft_meta_get_eval(const struct nft_expr *expr, - else - *dest = PACKET_BROADCAST; - break; -+ case NFPROTO_NETDEV: -+ switch (skb->protocol) { -+ case htons(ETH_P_IP): { -+ int noff = skb_network_offset(skb); -+ struct iphdr *iph, _iph; -+ -+ iph = skb_header_pointer(skb, noff, -+ sizeof(_iph), &_iph); -+ if (!iph) -+ goto err; -+ -+ if (ipv4_is_multicast(iph->daddr)) -+ *dest = PACKET_MULTICAST; -+ else -+ *dest = PACKET_BROADCAST; -+ -+ break; -+ } -+ case htons(ETH_P_IPV6): -+ *dest = PACKET_MULTICAST; -+ break; -+ default: -+ WARN_ON_ONCE(1); -+ goto err; -+ } -+ break; - default: -- WARN_ON(1); -+ WARN_ON_ONCE(1); - goto err; - } - break; -diff --git a/security/keys/trusted.c b/security/keys/trusted.c -index 509aedcf8310..214ae2dc7f64 100644 ---- a/security/keys/trusted.c -+++ b/security/keys/trusted.c -@@ -69,7 +69,7 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen, - } - - ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); -- kfree(sdesc); -+ kzfree(sdesc); - return ret; - } - -@@ -113,7 +113,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, - if (!ret) - ret = crypto_shash_final(&sdesc->shash, digest); - out: -- kfree(sdesc); -+ kzfree(sdesc); - return ret; - } - -@@ -164,7 +164,7 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key, - paramdigest, TPM_NONCE_SIZE, h1, - TPM_NONCE_SIZE, h2, 1, &c, 0, 0); - out: -- kfree(sdesc); -+ kzfree(sdesc); - return ret; - } - -@@ -245,7 +245,7 @@ static int TSS_checkhmac1(unsigned char *buffer, - if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) - ret = -EINVAL; - out: -- kfree(sdesc); -+ kzfree(sdesc); - return ret; - } - -@@ -346,7 +346,7 @@ static int TSS_checkhmac2(unsigned char *buffer, - if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) - ret = -EINVAL; - out: -- kfree(sdesc); -+ kzfree(sdesc); - return ret; - } - -@@ -563,7 +563,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, - *bloblen = storedsize; - } - out: -- kfree(td); -+ kzfree(td); - return ret; - } - -@@ -677,7 +677,7 @@ static int key_seal(struct trusted_key_payload *p, - if (ret < 0) - pr_info("trusted_key: srkseal failed (%d)\n", ret); - -- kfree(tb); -+ kzfree(tb); - return ret; - } - -@@ -702,7 +702,7 @@ static int key_unseal(struct trusted_key_payload *p, - /* pull migratable flag out of sealed key */ - p->migratable = p->key[--p->key_len]; - -- kfree(tb); -+ kzfree(tb); - return ret; - } - -@@ -984,12 +984,12 @@ static int trusted_instantiate(struct key *key, - if (!ret && options->pcrlock) - ret = pcrlock(options->pcrlock); - out: -- kfree(datablob); -- kfree(options); -+ kzfree(datablob); -+ kzfree(options); - if (!ret) - rcu_assign_keypointer(key, payload); - else -- kfree(payload); -+ kzfree(payload); - return ret; - } - -@@ -998,8 +998,7 @@ static void trusted_rcu_free(struct rcu_head *rcu) - struct trusted_key_payload *p; - - p = container_of(rcu, struct trusted_key_payload, rcu); -- memset(p->key, 0, p->key_len); -- kfree(p); -+ kzfree(p); - } - - /* -@@ -1041,13 +1040,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - ret = datablob_parse(datablob, new_p, new_o); - if (ret != Opt_update) { - ret = -EINVAL; -- kfree(new_p); -+ kzfree(new_p); - goto out; - } - - if (!new_o->keyhandle) { - ret = -EINVAL; -- kfree(new_p); -+ kzfree(new_p); - goto out; - } - -@@ -1061,22 +1060,22 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) - ret = key_seal(new_p, new_o); - if (ret < 0) { - pr_info("trusted_key: key_seal failed (%d)\n", ret); -- kfree(new_p); -+ kzfree(new_p); - goto out; - } - if (new_o->pcrlock) { - ret = pcrlock(new_o->pcrlock); - if (ret < 0) { - pr_info("trusted_key: pcrlock failed (%d)\n", ret); -- kfree(new_p); -+ kzfree(new_p); - goto out; - } - } - rcu_assign_keypointer(key, new_p); - call_rcu(&p->rcu, trusted_rcu_free); - out: -- kfree(datablob); -- kfree(new_o); -+ kzfree(datablob); -+ kzfree(new_o); - return ret; - } - -@@ -1095,34 +1094,30 @@ static long trusted_read(const struct key *key, char __user *buffer, - p = rcu_dereference_key(key); - if (!p) - return -EINVAL; -- if (!buffer || buflen <= 0) -- return 2 * p->blob_len; -- ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); -- if (!ascii_buf) -- return -ENOMEM; - -- bufp = ascii_buf; -- for (i = 0; i < p->blob_len; i++) -- bufp = hex_byte_pack(bufp, p->blob[i]); -- if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { -- kfree(ascii_buf); -- return -EFAULT; -+ if (buffer && buflen >= 2 * p->blob_len) { -+ ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); -+ if (!ascii_buf) -+ return -ENOMEM; -+ -+ bufp = ascii_buf; -+ for (i = 0; i < p->blob_len; i++) -+ bufp = hex_byte_pack(bufp, p->blob[i]); -+ if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { -+ kzfree(ascii_buf); -+ return -EFAULT; -+ } -+ kzfree(ascii_buf); - } -- kfree(ascii_buf); - return 2 * p->blob_len; - } - - /* -- * trusted_destroy - before freeing the key, clear the decrypted data -+ * trusted_destroy - clear and free the key's payload - */ - static void trusted_destroy(struct key *key) - { -- struct trusted_key_payload *p = key->payload.data[0]; -- -- if (!p) -- return; -- memset(p->key, 0, p->key_len); -- kfree(key->payload.data[0]); -+ kzfree(key->payload.data[0]); - } - - struct key_type key_type_trusted = { -diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c -index aaff9ee32695..b30b2139e3f0 100644 ---- a/sound/core/seq/oss/seq_oss_midi.c -+++ b/sound/core/seq/oss/seq_oss_midi.c -@@ -612,9 +612,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq - if (!dp->timer->running) - len = snd_seq_oss_timer_start(dp->timer); - if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { -- if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) -- snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, -- ev->data.ext.ptr, ev->data.ext.len); -+ snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev); - } else { - len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); - if (len > 0) -diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c -index 046cb586fb2f..06b21226b4e7 100644 ---- a/sound/core/seq/oss/seq_oss_readq.c -+++ b/sound/core/seq/oss/seq_oss_readq.c -@@ -117,6 +117,35 @@ snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, in - return 0; - } - -+/* -+ * put MIDI sysex bytes; the event buffer may be chained, thus it has -+ * to be expanded via snd_seq_dump_var_event(). -+ */ -+struct readq_sysex_ctx { -+ struct seq_oss_readq *readq; -+ int dev; -+}; -+ -+static int readq_dump_sysex(void *ptr, void *buf, int count) -+{ -+ struct readq_sysex_ctx *ctx = ptr; -+ -+ return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count); -+} -+ -+int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, -+ struct snd_seq_event *ev) -+{ -+ struct readq_sysex_ctx ctx = { -+ .readq = q, -+ .dev = dev -+ }; -+ -+ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) -+ return 0; -+ return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx); -+} -+ - /* - * copy an event to input queue: - * return zero if enqueued -diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h -index f1463f1f449e..8d033ca2d23f 100644 ---- a/sound/core/seq/oss/seq_oss_readq.h -+++ b/sound/core/seq/oss/seq_oss_readq.h -@@ -44,6 +44,8 @@ void snd_seq_oss_readq_delete(struct seq_oss_readq *q); - void snd_seq_oss_readq_clear(struct seq_oss_readq *readq); - unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait); - int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len); -+int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, -+ struct snd_seq_event *ev); - int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev); - int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode); - int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec); -diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh -index c4366dc74e01..856a1f327b3f 100755 ---- a/tools/testing/selftests/firmware/fw_filesystem.sh -+++ b/tools/testing/selftests/firmware/fw_filesystem.sh -@@ -48,8 +48,16 @@ echo "ABCD0123" >"$FW" - - NAME=$(basename "$FW") - -+if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then -+ echo "$0: empty filename should not succeed" >&2 -+ exit 1 -+fi -+ - # Request a firmware that doesn't exist, it should fail. --echo -n "nope-$NAME" >"$DIR"/trigger_request -+if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then -+ echo "$0: firmware shouldn't have loaded" >&2 -+ exit 1 -+fi - if diff -q "$FW" /dev/test_firmware >/dev/null ; then - echo "$0: firmware was not expected to match" >&2 - exit 1 -diff --git a/tools/testing/selftests/firmware/fw_userhelper.sh b/tools/testing/selftests/firmware/fw_userhelper.sh -index b9983f8e09f6..01c626a1f226 100755 ---- a/tools/testing/selftests/firmware/fw_userhelper.sh -+++ b/tools/testing/selftests/firmware/fw_userhelper.sh -@@ -64,9 +64,33 @@ trap "test_finish" EXIT - echo "ABCD0123" >"$FW" - NAME=$(basename "$FW") - -+DEVPATH="$DIR"/"nope-$NAME"/loading -+ - # Test failure when doing nothing (timeout works). --echo 1 >/sys/class/firmware/timeout --echo -n "$NAME" >"$DIR"/trigger_request -+echo -n 2 >/sys/class/firmware/timeout -+echo -n "nope-$NAME" >"$DIR"/trigger_request 2>/dev/null & -+ -+# Give the kernel some time to load the loading file, must be less -+# than the timeout above. -+sleep 1 -+if [ ! -f $DEVPATH ]; then -+ echo "$0: fallback mechanism immediately cancelled" -+ echo "" -+ echo "The file never appeared: $DEVPATH" -+ echo "" -+ echo "This might be a distribution udev rule setup by your distribution" -+ echo "to immediately cancel all fallback requests, this must be" -+ echo "removed before running these tests. To confirm look for" -+ echo "a firmware rule like /lib/udev/rules.d/50-firmware.rules" -+ echo "and see if you have something like this:" -+ echo "" -+ echo "SUBSYSTEM==\"firmware\", ACTION==\"add\", ATTR{loading}=\"-1\"" -+ echo "" -+ echo "If you do remove this file or comment out this line before" -+ echo "proceeding with these tests." -+ exit 1 -+fi -+ - if diff -q "$FW" /dev/test_firmware >/dev/null ; then - echo "$0: firmware was not expected to match" >&2 - exit 1 diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.98-99.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.98-99.patch deleted file mode 100644 index 0325797f3..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.98-99.patch +++ /dev/null @@ -1,1260 +0,0 @@ -diff --git a/Makefile b/Makefile -index 5d62e23347f9..0b5d9e20eee2 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 98 -+SUBLEVEL = 99 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig -index db49e0d796b1..dfb1ee8c3e06 100644 ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -1082,11 +1082,6 @@ source "arch/powerpc/Kconfig.debug" - - source "security/Kconfig" - --config KEYS_COMPAT -- bool -- depends on COMPAT && KEYS -- default y -- - source "crypto/Kconfig" - - config PPC_LIB_RHEAP -diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig -index 3a55f493c7da..5ad7b721b769 100644 ---- a/arch/s390/Kconfig -+++ b/arch/s390/Kconfig -@@ -346,9 +346,6 @@ config COMPAT - config SYSVIPC_COMPAT - def_bool y if COMPAT && SYSVIPC - --config KEYS_COMPAT -- def_bool y if COMPAT && KEYS -- - config SMP - def_bool y - prompt "Symmetric multi-processing support" -diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig -index eb9487470141..94f4ac21761b 100644 ---- a/arch/sparc/Kconfig -+++ b/arch/sparc/Kconfig -@@ -549,9 +549,6 @@ config SYSVIPC_COMPAT - depends on COMPAT && SYSVIPC - default y - --config KEYS_COMPAT -- def_bool y if COMPAT && KEYS -- - endmenu - - source "net/Kconfig" -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index 436639a31624..7e40905f6d4c 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -2641,10 +2641,6 @@ config COMPAT_FOR_U64_ALIGNMENT - config SYSVIPC_COMPAT - def_bool y - depends on SYSVIPC -- --config KEYS_COMPAT -- def_bool y -- depends on KEYS - endif - - endmenu -diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c -index f4e8fbec6a94..b5304e264881 100644 ---- a/drivers/input/misc/ims-pcu.c -+++ b/drivers/input/misc/ims-pcu.c -@@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf) - return NULL; - } - -- while (buflen > 0) { -+ while (buflen >= sizeof(*union_desc)) { - union_desc = (struct usb_cdc_union_desc *)buf; - -+ if (union_desc->bLength > buflen) { -+ dev_err(&intf->dev, "Too large descriptor\n"); -+ return NULL; -+ } -+ - if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE && - union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) { - dev_dbg(&intf->dev, "Found union header\n"); -- return union_desc; -+ -+ if (union_desc->bLength >= sizeof(*union_desc)) -+ return union_desc; -+ -+ dev_err(&intf->dev, -+ "Union descriptor to short (%d vs %zd\n)", -+ union_desc->bLength, sizeof(*union_desc)); -+ return NULL; - } - - buflen -= union_desc->bLength; -diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c -index 79de9608ac48..ed96fdefd8e5 100644 ---- a/drivers/net/macvtap.c -+++ b/drivers/net/macvtap.c -@@ -1117,6 +1117,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, - case TUNSETSNDBUF: - if (get_user(s, sp)) - return -EFAULT; -+ if (s <= 0) -+ return -EINVAL; - - q->sk.sk_sndbuf = s; - return 0; -diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c -index e5bb870b5461..dc454138d600 100644 ---- a/drivers/net/ppp/ppp_generic.c -+++ b/drivers/net/ppp/ppp_generic.c -@@ -1110,7 +1110,17 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) - static struct lock_class_key ppp_tx_busylock; - static int ppp_dev_init(struct net_device *dev) - { -+ struct ppp *ppp; -+ - dev->qdisc_tx_busylock = &ppp_tx_busylock; -+ -+ ppp = netdev_priv(dev); -+ /* Let the netdevice take a reference on the ppp file. This ensures -+ * that ppp_destroy_interface() won't run before the device gets -+ * unregistered. -+ */ -+ atomic_inc(&ppp->file.refcnt); -+ - return 0; - } - -@@ -1133,6 +1143,15 @@ static void ppp_dev_uninit(struct net_device *dev) - wake_up_interruptible(&ppp->file.rwait); - } - -+static void ppp_dev_priv_destructor(struct net_device *dev) -+{ -+ struct ppp *ppp; -+ -+ ppp = netdev_priv(dev); -+ if (atomic_dec_and_test(&ppp->file.refcnt)) -+ ppp_destroy_interface(ppp); -+} -+ - static const struct net_device_ops ppp_netdev_ops = { - .ndo_init = ppp_dev_init, - .ndo_uninit = ppp_dev_uninit, -@@ -1150,6 +1169,7 @@ static void ppp_setup(struct net_device *dev) - dev->tx_queue_len = 3; - dev->type = ARPHRD_PPP; - dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; -+ dev->destructor = ppp_dev_priv_destructor; - netif_keep_dst(dev); - } - -diff --git a/drivers/net/tun.c b/drivers/net/tun.c -index cd191f82d816..50bfded6d7ef 100644 ---- a/drivers/net/tun.c -+++ b/drivers/net/tun.c -@@ -1684,6 +1684,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) - - if (!dev) - return -ENOMEM; -+ err = dev_get_valid_name(net, dev, name); -+ if (err < 0) -+ goto err_free_dev; - - dev_net_set(dev, net); - dev->rtnl_link_ops = &tun_link_ops; -@@ -2065,6 +2068,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, - ret = -EFAULT; - break; - } -+ if (sndbuf <= 0) { -+ ret = -EINVAL; -+ break; -+ } - - tun->sndbuf = sndbuf; - tun_set_sndbuf(tun); -diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -index 5fecae0ba52e..83e5aa6a9f28 100644 ---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c -@@ -4295,9 +4295,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); - if (err < 0) - brcmf_err("setting AP mode failed %d\n", err); -- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0); -- if (err < 0) -- brcmf_err("setting INFRA mode failed %d\n", err); - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) - brcmf_fil_iovar_int_set(ifp, "mbss", 0); - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, -diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c -index 70b8f4fabfad..e658e11e1829 100644 ---- a/drivers/staging/panel/panel.c -+++ b/drivers/staging/panel/panel.c -@@ -1431,17 +1431,25 @@ static ssize_t lcd_write(struct file *file, - - static int lcd_open(struct inode *inode, struct file *file) - { -+ int ret; -+ -+ ret = -EBUSY; - if (!atomic_dec_and_test(&lcd_available)) -- return -EBUSY; /* open only once at a time */ -+ goto fail; /* open only once at a time */ - -+ ret = -EPERM; - if (file->f_mode & FMODE_READ) /* device is write-only */ -- return -EPERM; -+ goto fail; - - if (lcd.must_clear) { - lcd_clear_display(); - lcd.must_clear = false; - } - return nonseekable_open(inode, file); -+ -+ fail: -+ atomic_inc(&lcd_available); -+ return ret; - } - - static int lcd_release(struct inode *inode, struct file *file) -@@ -1704,14 +1712,21 @@ static ssize_t keypad_read(struct file *file, - - static int keypad_open(struct inode *inode, struct file *file) - { -+ int ret; -+ -+ ret = -EBUSY; - if (!atomic_dec_and_test(&keypad_available)) -- return -EBUSY; /* open only once at a time */ -+ goto fail; /* open only once at a time */ - -+ ret = -EPERM; - if (file->f_mode & FMODE_WRITE) /* device is read-only */ -- return -EPERM; -+ goto fail; - - keypad_buflen = 0; /* flush the buffer on opening */ - return 0; -+ fail: -+ atomic_inc(&keypad_available); -+ return ret; - } - - static int keypad_release(struct inode *inode, struct file *file) -diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c -index 1ff1c83e2df5..fd493412b172 100644 ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -1759,7 +1759,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, - struct iscsi_tm *hdr; - int out_of_order_cmdsn = 0, ret; - bool sess_ref = false; -- u8 function; -+ u8 function, tcm_function = TMR_UNKNOWN; - - hdr = (struct iscsi_tm *) buf; - hdr->flags &= ~ISCSI_FLAG_CMD_FINAL; -@@ -1805,10 +1805,6 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, - * LIO-Target $FABRIC_MOD - */ - if (function != ISCSI_TM_FUNC_TASK_REASSIGN) { -- -- u8 tcm_function; -- int ret; -- - transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops, - conn->sess->se_sess, 0, DMA_NONE, - TCM_SIMPLE_TAG, cmd->sense_buffer + 2); -@@ -1844,15 +1840,14 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, - return iscsit_add_reject_cmd(cmd, - ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); - } -- -- ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, -- tcm_function, GFP_KERNEL); -- if (ret < 0) -- return iscsit_add_reject_cmd(cmd, -+ } -+ ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function, -+ GFP_KERNEL); -+ if (ret < 0) -+ return iscsit_add_reject_cmd(cmd, - ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); - -- cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req; -- } -+ cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req; - - cmd->iscsi_opcode = ISCSI_OP_SCSI_TMFUNC; - cmd->i_state = ISTATE_SEND_TASKMGTRSP; -diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c -index f69f4902dc07..ee16a45f1607 100644 ---- a/drivers/target/target_core_tpg.c -+++ b/drivers/target/target_core_tpg.c -@@ -350,7 +350,7 @@ void core_tpg_del_initiator_node_acl(struct se_node_acl *acl) - if (acl->dynamic_node_acl) { - acl->dynamic_node_acl = 0; - } -- list_del(&acl->acl_list); -+ list_del_init(&acl->acl_list); - tpg->num_node_acls--; - mutex_unlock(&tpg->acl_node_mutex); - -@@ -572,7 +572,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) - * in transport_deregister_session(). - */ - list_for_each_entry_safe(nacl, nacl_tmp, &node_list, acl_list) { -- list_del(&nacl->acl_list); -+ list_del_init(&nacl->acl_list); - se_tpg->num_node_acls--; - - core_tpg_wait_for_nacl_pr_ref(nacl); -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index f71bedea973a..a42054edd427 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -431,7 +431,7 @@ static void target_complete_nacl(struct kref *kref) - } - - mutex_lock(&se_tpg->acl_node_mutex); -- list_del(&nacl->acl_list); -+ list_del_init(&nacl->acl_list); - mutex_unlock(&se_tpg->acl_node_mutex); - - core_tpg_wait_for_nacl_pr_ref(nacl); -@@ -503,7 +503,7 @@ void transport_free_session(struct se_session *se_sess) - spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags); - - if (se_nacl->dynamic_stop) -- list_del(&se_nacl->acl_list); -+ list_del_init(&se_nacl->acl_list); - } - mutex_unlock(&se_tpg->acl_node_mutex); - -diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c -index 2e947dc94e32..bc92a498ec03 100644 ---- a/drivers/usb/misc/usbtest.c -+++ b/drivers/usb/misc/usbtest.c -@@ -185,12 +185,13 @@ found: - return tmp; - } - -- if (in) { -+ if (in) - dev->in_pipe = usb_rcvbulkpipe(udev, - in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); -+ if (out) - dev->out_pipe = usb_sndbulkpipe(udev, - out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); -- } -+ - if (iso_in) { - dev->iso_in = &iso_in->desc; - dev->in_iso_pipe = usb_rcvisocpipe(udev, -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index 4035bbe40971..fc54049e8286 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -3469,6 +3469,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, - unsigned char name_assign_type, - void (*setup)(struct net_device *), - unsigned int txqs, unsigned int rxqs); -+int dev_get_valid_name(struct net *net, struct net_device *dev, -+ const char *name); -+ - #define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ - alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, 1, 1) - -diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h -index 625bdf95d673..95aa999f31d7 100644 ---- a/include/net/inet_sock.h -+++ b/include/net/inet_sock.h -@@ -95,7 +95,7 @@ struct inet_request_sock { - kmemcheck_bitfield_end(flags); - u32 ir_mark; - union { -- struct ip_options_rcu *opt; -+ struct ip_options_rcu __rcu *ireq_opt; - struct sk_buff *pktopts; - }; - }; -@@ -113,6 +113,12 @@ static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) - return sk->sk_mark; - } - -+static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq) -+{ -+ return rcu_dereference_check(ireq->ireq_opt, -+ atomic_read(&ireq->req.rsk_refcnt) > 0); -+} -+ - struct inet_cork { - unsigned int flags; - __be32 addr; -diff --git a/include/net/tcp.h b/include/net/tcp.h -index e9d7a8ef9a6d..cecb0e0eff06 100644 ---- a/include/net/tcp.h -+++ b/include/net/tcp.h -@@ -1612,12 +1612,12 @@ static inline void tcp_highest_sack_reset(struct sock *sk) - tcp_sk(sk)->highest_sack = tcp_write_queue_head(sk); - } - --/* Called when old skb is about to be deleted (to be combined with new skb) */ --static inline void tcp_highest_sack_combine(struct sock *sk, -+/* Called when old skb is about to be deleted and replaced by new skb */ -+static inline void tcp_highest_sack_replace(struct sock *sk, - struct sk_buff *old, - struct sk_buff *new) - { -- if (tcp_sk(sk)->sacked_out && (old == tcp_sk(sk)->highest_sack)) -+ if (old == tcp_highest_sack(sk)) - tcp_sk(sk)->highest_sack = new; - } - -diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h -index 1adf8739980c..8555321306fb 100644 ---- a/include/target/target_core_base.h -+++ b/include/target/target_core_base.h -@@ -199,6 +199,7 @@ enum tcm_tmreq_table { - TMR_LUN_RESET = 5, - TMR_TARGET_WARM_RESET = 6, - TMR_TARGET_COLD_RESET = 7, -+ TMR_UNKNOWN = 0xff, - }; - - /* fabric independent task management response values */ -diff --git a/net/core/dev.c b/net/core/dev.c -index dac52fa60f25..630704d8d6a2 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -1111,9 +1111,8 @@ static int dev_alloc_name_ns(struct net *net, - return ret; - } - --static int dev_get_valid_name(struct net *net, -- struct net_device *dev, -- const char *name) -+int dev_get_valid_name(struct net *net, struct net_device *dev, -+ const char *name) - { - BUG_ON(!net); - -@@ -1129,6 +1128,7 @@ static int dev_get_valid_name(struct net *net, - - return 0; - } -+EXPORT_SYMBOL(dev_get_valid_name); - - /** - * dev_change_name - change name of a device -diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c -index e217f17997a4..6eb2bbf9873b 100644 ---- a/net/dccp/ipv4.c -+++ b/net/dccp/ipv4.c -@@ -414,8 +414,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, - sk_daddr_set(newsk, ireq->ir_rmt_addr); - sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); - newinet->inet_saddr = ireq->ir_loc_addr; -- newinet->inet_opt = ireq->opt; -- ireq->opt = NULL; -+ RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt)); - newinet->mc_index = inet_iif(skb); - newinet->mc_ttl = ip_hdr(skb)->ttl; - newinet->inet_id = jiffies; -@@ -430,7 +429,10 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, - if (__inet_inherit_port(sk, newsk) < 0) - goto put_and_exit; - *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); -- -+ if (*own_req) -+ ireq->ireq_opt = NULL; -+ else -+ newinet->inet_opt = NULL; - return newsk; - - exit_overflow: -@@ -441,6 +443,7 @@ exit: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); - return NULL; - put_and_exit: -+ newinet->inet_opt = NULL; - inet_csk_prepare_forced_close(newsk); - dccp_done(newsk); - goto exit; -@@ -492,7 +495,7 @@ static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req - ireq->ir_rmt_addr); - err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, - ireq->ir_rmt_addr, -- ireq->opt); -+ ireq_opt_deref(ireq)); - err = net_xmit_eval(err); - } - -@@ -546,7 +549,7 @@ out: - static void dccp_v4_reqsk_destructor(struct request_sock *req) - { - dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg); -- kfree(inet_rsk(req)->opt); -+ kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1)); - } - - void dccp_syn_ack_timeout(const struct request_sock *req) -diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c -index 6cc3e1d602fb..5f3b81941a6f 100644 ---- a/net/ipv4/cipso_ipv4.c -+++ b/net/ipv4/cipso_ipv4.c -@@ -2012,7 +2012,7 @@ int cipso_v4_req_setattr(struct request_sock *req, - buf = NULL; - - req_inet = inet_rsk(req); -- opt = xchg(&req_inet->opt, opt); -+ opt = xchg((__force struct ip_options_rcu **)&req_inet->ireq_opt, opt); - if (opt) - kfree_rcu(opt, rcu); - -@@ -2034,11 +2034,13 @@ req_setattr_failure: - * values on failure. - * - */ --static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr) -+static int cipso_v4_delopt(struct ip_options_rcu __rcu **opt_ptr) - { -+ struct ip_options_rcu *opt = rcu_dereference_protected(*opt_ptr, 1); - int hdr_delta = 0; -- struct ip_options_rcu *opt = *opt_ptr; - -+ if (!opt || opt->opt.cipso == 0) -+ return 0; - if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) { - u8 cipso_len; - u8 cipso_off; -@@ -2100,14 +2102,10 @@ static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr) - */ - void cipso_v4_sock_delattr(struct sock *sk) - { -- int hdr_delta; -- struct ip_options_rcu *opt; - struct inet_sock *sk_inet; -+ int hdr_delta; - - sk_inet = inet_sk(sk); -- opt = rcu_dereference_protected(sk_inet->inet_opt, 1); -- if (!opt || opt->opt.cipso == 0) -- return; - - hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); - if (sk_inet->is_icsk && hdr_delta > 0) { -@@ -2127,15 +2125,7 @@ void cipso_v4_sock_delattr(struct sock *sk) - */ - void cipso_v4_req_delattr(struct request_sock *req) - { -- struct ip_options_rcu *opt; -- struct inet_request_sock *req_inet; -- -- req_inet = inet_rsk(req); -- opt = req_inet->opt; -- if (!opt || opt->opt.cipso == 0) -- return; -- -- cipso_v4_delopt(&req_inet->opt); -+ cipso_v4_delopt(&inet_rsk(req)->ireq_opt); - } - - /** -diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c -index 45fa2aaa3d3f..01acb94c4963 100644 ---- a/net/ipv4/inet_connection_sock.c -+++ b/net/ipv4/inet_connection_sock.c -@@ -412,9 +412,11 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk, - { - const struct inet_request_sock *ireq = inet_rsk(req); - struct net *net = read_pnet(&ireq->ireq_net); -- struct ip_options_rcu *opt = ireq->opt; -+ struct ip_options_rcu *opt; - struct rtable *rt; - -+ opt = ireq_opt_deref(ireq); -+ - flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark, - RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, - sk->sk_protocol, inet_sk_flowi_flags(sk), -@@ -448,10 +450,9 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, - struct flowi4 *fl4; - struct rtable *rt; - -+ opt = rcu_dereference(ireq->ireq_opt); - fl4 = &newinet->cork.fl.u.ip4; - -- rcu_read_lock(); -- opt = rcu_dereference(newinet->inet_opt); - flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark, - RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, - sk->sk_protocol, inet_sk_flowi_flags(sk), -@@ -464,13 +465,11 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk, - goto no_route; - if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) - goto route_err; -- rcu_read_unlock(); - return &rt->dst; - - route_err: - ip_rt_put(rt); - no_route: -- rcu_read_unlock(); - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); - return NULL; - } -diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c -index a09fb0dec725..486b283a6cd1 100644 ---- a/net/ipv4/ipip.c -+++ b/net/ipv4/ipip.c -@@ -129,42 +129,68 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly; - static int ipip_err(struct sk_buff *skb, u32 info) - { - --/* All the routers (except for Linux) return only -- 8 bytes of packet payload. It means, that precise relaying of -- ICMP in the real Internet is absolutely infeasible. -- */ -+ /* All the routers (except for Linux) return only -+ 8 bytes of packet payload. It means, that precise relaying of -+ ICMP in the real Internet is absolutely infeasible. -+ */ - struct net *net = dev_net(skb->dev); - struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); - const struct iphdr *iph = (const struct iphdr *)skb->data; -- struct ip_tunnel *t; -- int err; - const int type = icmp_hdr(skb)->type; - const int code = icmp_hdr(skb)->code; -+ struct ip_tunnel *t; -+ int err = 0; -+ -+ switch (type) { -+ case ICMP_DEST_UNREACH: -+ switch (code) { -+ case ICMP_SR_FAILED: -+ /* Impossible event. */ -+ goto out; -+ default: -+ /* All others are translated to HOST_UNREACH. -+ * rfc2003 contains "deep thoughts" about NET_UNREACH, -+ * I believe they are just ether pollution. --ANK -+ */ -+ break; -+ } -+ break; -+ -+ case ICMP_TIME_EXCEEDED: -+ if (code != ICMP_EXC_TTL) -+ goto out; -+ break; -+ -+ case ICMP_REDIRECT: -+ break; -+ -+ default: -+ goto out; -+ } - -- err = -ENOENT; - t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, - iph->daddr, iph->saddr, 0); -- if (!t) -+ if (!t) { -+ err = -ENOENT; - goto out; -+ } - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { -- ipv4_update_pmtu(skb, dev_net(skb->dev), info, -- t->parms.link, 0, IPPROTO_IPIP, 0); -- err = 0; -+ ipv4_update_pmtu(skb, net, info, t->parms.link, 0, -+ iph->protocol, 0); - goto out; - } - - if (type == ICMP_REDIRECT) { -- ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, -- IPPROTO_IPIP, 0); -- err = 0; -+ ipv4_redirect(skb, net, t->parms.link, 0, iph->protocol, 0); - goto out; - } - -- if (t->parms.iph.daddr == 0) -+ if (t->parms.iph.daddr == 0) { -+ err = -ENOENT; - goto out; -+ } - -- err = 0; - if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) - goto out; - -diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c -index 731b91409625..c22a74374a9c 100644 ---- a/net/ipv4/syncookies.c -+++ b/net/ipv4/syncookies.c -@@ -357,7 +357,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) - /* We throwed the options of the initial SYN away, so we hope - * the ACK carries the same options again (see RFC1122 4.2.3.8) - */ -- ireq->opt = tcp_v4_save_options(skb); -+ RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(skb)); - - if (security_inet_conn_request(sk, skb, req)) { - reqsk_free(req); -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index c4bbf704ff9c..9e8d70160d20 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -6105,7 +6105,7 @@ struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops, - struct inet_request_sock *ireq = inet_rsk(req); - - kmemcheck_annotate_bitfield(ireq, flags); -- ireq->opt = NULL; -+ ireq->ireq_opt = NULL; - atomic64_set(&ireq->ir_cookie, 0); - ireq->ireq_state = TCP_NEW_SYN_RECV; - write_pnet(&ireq->ireq_net, sock_net(sk_listener)); -diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c -index 198fc2314c82..a5d790c13ef5 100644 ---- a/net/ipv4/tcp_ipv4.c -+++ b/net/ipv4/tcp_ipv4.c -@@ -856,7 +856,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, - - err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr, - ireq->ir_rmt_addr, -- ireq->opt); -+ ireq_opt_deref(ireq)); - err = net_xmit_eval(err); - } - -@@ -868,7 +868,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst, - */ - static void tcp_v4_reqsk_destructor(struct request_sock *req) - { -- kfree(inet_rsk(req)->opt); -+ kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1)); - } - - -@@ -1197,7 +1197,7 @@ static void tcp_v4_init_req(struct request_sock *req, - sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr); - sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr); - ireq->no_srccheck = inet_sk(sk_listener)->transparent; -- ireq->opt = tcp_v4_save_options(skb); -+ RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(skb)); - } - - static struct dst_entry *tcp_v4_route_req(const struct sock *sk, -@@ -1292,10 +1292,9 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, - ireq = inet_rsk(req); - sk_daddr_set(newsk, ireq->ir_rmt_addr); - sk_rcv_saddr_set(newsk, ireq->ir_loc_addr); -- newinet->inet_saddr = ireq->ir_loc_addr; -- inet_opt = ireq->opt; -- rcu_assign_pointer(newinet->inet_opt, inet_opt); -- ireq->opt = NULL; -+ newinet->inet_saddr = ireq->ir_loc_addr; -+ inet_opt = rcu_dereference(ireq->ireq_opt); -+ RCU_INIT_POINTER(newinet->inet_opt, inet_opt); - newinet->mc_index = inet_iif(skb); - newinet->mc_ttl = ip_hdr(skb)->ttl; - newinet->rcv_tos = ip_hdr(skb)->tos; -@@ -1343,9 +1342,12 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, - if (__inet_inherit_port(sk, newsk) < 0) - goto put_and_exit; - *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash)); -- if (*own_req) -+ if (likely(*own_req)) { - tcp_move_syn(newtp, req); -- -+ ireq->ireq_opt = NULL; -+ } else { -+ newinet->inet_opt = NULL; -+ } - return newsk; - - exit_overflow: -@@ -1356,6 +1358,7 @@ exit: - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); - return NULL; - put_and_exit: -+ newinet->inet_opt = NULL; - inet_csk_prepare_forced_close(newsk); - tcp_done(newsk); - goto exit; -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 850d1b5bfd81..64c7ce847584 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -1951,6 +1951,7 @@ static int tcp_mtu_probe(struct sock *sk) - nskb->ip_summed = skb->ip_summed; - - tcp_insert_write_queue_before(nskb, skb, sk); -+ tcp_highest_sack_replace(sk, skb, nskb); - - len = 0; - tcp_for_write_queue_from_safe(skb, next, sk) { -@@ -2464,7 +2465,7 @@ static void tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb) - - BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1); - -- tcp_highest_sack_combine(sk, next_skb, skb); -+ tcp_highest_sack_replace(sk, next_skb, skb); - - tcp_unlink_write_queue(next_skb, sk); - -diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c -index dc2db4f7b182..f3a0a9c0f61e 100644 ---- a/net/ipv6/ip6_flowlabel.c -+++ b/net/ipv6/ip6_flowlabel.c -@@ -315,6 +315,7 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, - } - opt_space->dst1opt = fopt->dst1opt; - opt_space->opt_flen = fopt->opt_flen; -+ opt_space->tot_len = fopt->tot_len; - return opt_space; - } - EXPORT_SYMBOL_GPL(fl6_merge_options); -diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c -index eab117033b8a..c878cbf65485 100644 ---- a/net/ipv6/ip6_gre.c -+++ b/net/ipv6/ip6_gre.c -@@ -409,13 +409,16 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - case ICMPV6_DEST_UNREACH: - net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", - t->parms.name); -- break; -+ if (code != ICMPV6_PORT_UNREACH) -+ break; -+ return; - case ICMPV6_TIME_EXCEED: - if (code == ICMPV6_EXC_HOPLIMIT) { - net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", - t->parms.name); -+ break; - } -- break; -+ return; - case ICMPV6_PARAMPROB: - teli = 0; - if (code == ICMPV6_HDR_FIELD) -@@ -431,13 +434,13 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", - t->parms.name); - } -- break; -+ return; - case ICMPV6_PKT_TOOBIG: - mtu = be32_to_cpu(info) - offset; - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - t->dev->mtu = mtu; -- break; -+ return; - } - - if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index e22339fad10b..71624cf26832 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1201,11 +1201,11 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, - if (WARN_ON(v6_cork->opt)) - return -EINVAL; - -- v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation); -+ v6_cork->opt = kzalloc(sizeof(*opt), sk->sk_allocation); - if (unlikely(!v6_cork->opt)) - return -ENOBUFS; - -- v6_cork->opt->tot_len = opt->tot_len; -+ v6_cork->opt->tot_len = sizeof(*opt); - v6_cork->opt->opt_flen = opt->opt_flen; - v6_cork->opt->opt_nflen = opt->opt_nflen; - -diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c -index 8ab9c5d74416..67f2e72723b2 100644 ---- a/net/l2tp/l2tp_ppp.c -+++ b/net/l2tp/l2tp_ppp.c -@@ -1015,6 +1015,9 @@ static int pppol2tp_session_ioctl(struct l2tp_session *session, - session->name, cmd, arg); - - sk = ps->sock; -+ if (!sk) -+ return -EBADR; -+ - sock_hold(sk); - - switch (cmd) { -diff --git a/net/mac80211/key.c b/net/mac80211/key.c -index 44388d6a1d8e..4a72c0d1e56f 100644 ---- a/net/mac80211/key.c -+++ b/net/mac80211/key.c -@@ -4,6 +4,7 @@ - * Copyright 2006-2007 Jiri Benc - * Copyright 2007-2008 Johannes Berg - * Copyright 2013-2014 Intel Mobile Communications GmbH -+ * Copyright 2017 Intel Deutschland GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -18,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include "ieee80211_i.h" - #include "driver-ops.h" -@@ -606,6 +608,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key) - ieee80211_key_free_common(key); - } - -+static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_key *old, -+ struct ieee80211_key *new) -+{ -+ u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP]; -+ u8 *tk_old, *tk_new; -+ -+ if (!old || new->conf.keylen != old->conf.keylen) -+ return false; -+ -+ tk_old = old->conf.key; -+ tk_new = new->conf.key; -+ -+ /* -+ * In station mode, don't compare the TX MIC key, as it's never used -+ * and offloaded rekeying may not care to send it to the host. This -+ * is the case in iwlwifi, for example. -+ */ -+ if (sdata->vif.type == NL80211_IFTYPE_STATION && -+ new->conf.cipher == WLAN_CIPHER_SUITE_TKIP && -+ new->conf.keylen == WLAN_KEY_LEN_TKIP && -+ !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) { -+ memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP); -+ memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP); -+ memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); -+ memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); -+ tk_old = tkip_old; -+ tk_new = tkip_new; -+ } -+ -+ return !crypto_memneq(tk_old, tk_new, new->conf.keylen); -+} -+ - int ieee80211_key_link(struct ieee80211_key *key, - struct ieee80211_sub_if_data *sdata, - struct sta_info *sta) -@@ -617,9 +652,6 @@ int ieee80211_key_link(struct ieee80211_key *key, - - pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; - idx = key->conf.keyidx; -- key->local = sdata->local; -- key->sdata = sdata; -- key->sta = sta; - - mutex_lock(&sdata->local->key_mtx); - -@@ -630,6 +662,20 @@ int ieee80211_key_link(struct ieee80211_key *key, - else - old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); - -+ /* -+ * Silently accept key re-installation without really installing the -+ * new version of the key to avoid nonce reuse or replay issues. -+ */ -+ if (ieee80211_key_identical(sdata, old_key, key)) { -+ ieee80211_key_free_unused(key); -+ ret = 0; -+ goto out; -+ } -+ -+ key->local = sdata->local; -+ key->sdata = sdata; -+ key->sta = sta; -+ - increment_tailroom_need_count(sdata); - - ieee80211_key_replace(sdata, sta, pairwise, old_key, key); -@@ -645,6 +691,7 @@ int ieee80211_key_link(struct ieee80211_key *key, - ret = 0; - } - -+ out: - mutex_unlock(&sdata->local->key_mtx); - - return ret; -diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c -index 241f69039a72..1584f89c456a 100644 ---- a/net/packet/af_packet.c -+++ b/net/packet/af_packet.c -@@ -1724,7 +1724,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) - - out: - if (err && rollover) { -- kfree(rollover); -+ kfree_rcu(rollover, rcu); - po->rollover = NULL; - } - mutex_unlock(&fanout_mutex); -@@ -1751,8 +1751,10 @@ static struct packet_fanout *fanout_release(struct sock *sk) - else - f = NULL; - -- if (po->rollover) -+ if (po->rollover) { - kfree_rcu(po->rollover, rcu); -+ po->rollover = NULL; -+ } - } - mutex_unlock(&fanout_mutex); - -@@ -3769,6 +3771,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, - void *data = &val; - union tpacket_stats_u st; - struct tpacket_rollover_stats rstats; -+ struct packet_rollover *rollover; - - if (level != SOL_PACKET) - return -ENOPROTOOPT; -@@ -3847,13 +3850,18 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, - 0); - break; - case PACKET_ROLLOVER_STATS: -- if (!po->rollover) -+ rcu_read_lock(); -+ rollover = rcu_dereference(po->rollover); -+ if (rollover) { -+ rstats.tp_all = atomic_long_read(&rollover->num); -+ rstats.tp_huge = atomic_long_read(&rollover->num_huge); -+ rstats.tp_failed = atomic_long_read(&rollover->num_failed); -+ data = &rstats; -+ lv = sizeof(rstats); -+ } -+ rcu_read_unlock(); -+ if (!rollover) - return -EINVAL; -- rstats.tp_all = atomic_long_read(&po->rollover->num); -- rstats.tp_huge = atomic_long_read(&po->rollover->num_huge); -- rstats.tp_failed = atomic_long_read(&po->rollover->num_failed); -- data = &rstats; -- lv = sizeof(rstats); - break; - case PACKET_TX_HAS_OFF: - val = po->tp_tx_has_off; -diff --git a/net/sctp/input.c b/net/sctp/input.c -index 2d7859c03fd2..71c2ef84c5b0 100644 ---- a/net/sctp/input.c -+++ b/net/sctp/input.c -@@ -420,7 +420,7 @@ void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t, - { - struct dst_entry *dst; - -- if (!t) -+ if (sock_owned_by_user(sk) || !t) - return; - dst = sctp_transport_dst_check(t); - if (dst) -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 3ebf3b652d60..73eec73ff733 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -168,6 +168,36 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk) - sk_mem_charge(sk, chunk->skb->truesize); - } - -+static void sctp_clear_owner_w(struct sctp_chunk *chunk) -+{ -+ skb_orphan(chunk->skb); -+} -+ -+static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, -+ void (*cb)(struct sctp_chunk *)) -+ -+{ -+ struct sctp_outq *q = &asoc->outqueue; -+ struct sctp_transport *t; -+ struct sctp_chunk *chunk; -+ -+ list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) -+ list_for_each_entry(chunk, &t->transmitted, transmitted_list) -+ cb(chunk); -+ -+ list_for_each_entry(chunk, &q->retransmit, list) -+ cb(chunk); -+ -+ list_for_each_entry(chunk, &q->sacked, list) -+ cb(chunk); -+ -+ list_for_each_entry(chunk, &q->abandoned, list) -+ cb(chunk); -+ -+ list_for_each_entry(chunk, &q->out_chunk_list, list) -+ cb(chunk); -+} -+ - /* Verify that this is a valid address. */ - static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, - int len) -@@ -7362,7 +7392,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, - * paths won't try to lock it and then oldsk. - */ - lock_sock_nested(newsk, SINGLE_DEPTH_NESTING); -+ sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w); - sctp_assoc_migrate(assoc, newsk); -+ sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w); - - /* If the association on the newsk is already closed before accept() - * is called, set RCV_SHUTDOWN flag. -diff --git a/net/tipc/link.c b/net/tipc/link.c -index 72268eac4ec7..736fffb28ab6 100644 ---- a/net/tipc/link.c -+++ b/net/tipc/link.c -@@ -1084,25 +1084,6 @@ drop: - return rc; - } - --/* -- * Send protocol message to the other endpoint. -- */ --void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, int probe_msg, -- u32 gap, u32 tolerance, u32 priority) --{ -- struct sk_buff *skb = NULL; -- struct sk_buff_head xmitq; -- -- __skb_queue_head_init(&xmitq); -- tipc_link_build_proto_msg(l, msg_typ, probe_msg, gap, -- tolerance, priority, &xmitq); -- skb = __skb_dequeue(&xmitq); -- if (!skb) -- return; -- tipc_bearer_xmit_skb(l->net, l->bearer_id, skb, l->media_addr); -- l->rcv_unacked = 0; --} -- - static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, - u16 rcvgap, int tolerance, int priority, - struct sk_buff_head *xmitq) -@@ -1636,9 +1617,12 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) - char *name; - struct tipc_link *link; - struct tipc_node *node; -+ struct sk_buff_head xmitq; - struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; - struct net *net = sock_net(skb->sk); - -+ __skb_queue_head_init(&xmitq); -+ - if (!info->attrs[TIPC_NLA_LINK]) - return -EINVAL; - -@@ -1683,14 +1667,14 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) - - tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); - link->tolerance = tol; -- tipc_link_proto_xmit(link, STATE_MSG, 0, 0, tol, 0); -+ tipc_link_build_proto_msg(link, STATE_MSG, 0, 0, tol, 0, &xmitq); - } - if (props[TIPC_NLA_PROP_PRIO]) { - u32 prio; - - prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); - link->priority = prio; -- tipc_link_proto_xmit(link, STATE_MSG, 0, 0, 0, prio); -+ tipc_link_build_proto_msg(link, STATE_MSG, 0, 0, 0, prio, &xmitq); - } - if (props[TIPC_NLA_PROP_WIN]) { - u32 win; -@@ -1702,7 +1686,7 @@ int tipc_nl_link_set(struct sk_buff *skb, struct genl_info *info) - - out: - tipc_node_unlock(node); -- -+ tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr); - return res; - } - -diff --git a/net/tipc/link.h b/net/tipc/link.h -index 66d859b66c84..2a0d58671e88 100644 ---- a/net/tipc/link.h -+++ b/net/tipc/link.h -@@ -153,7 +153,6 @@ struct tipc_stats { - struct tipc_link { - u32 addr; - char name[TIPC_MAX_LINK_NAME]; -- struct tipc_media_addr *media_addr; - struct net *net; - - /* Management and link supervision data */ -diff --git a/net/unix/diag.c b/net/unix/diag.c -index 4d9679701a6d..384c84e83462 100644 ---- a/net/unix/diag.c -+++ b/net/unix/diag.c -@@ -257,6 +257,8 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, - err = -ENOENT; - if (sk == NULL) - goto out_nosk; -+ if (!net_eq(sock_net(sk), net)) -+ goto out; - - err = sock_diag_check_cookie(sk, req->udiag_cookie); - if (err) -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index 72483b8f1be5..1edb37eea81d 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -20,6 +20,10 @@ config KEYS - - If you are unsure as to whether this is required, answer N. - -+config KEYS_COMPAT -+ def_bool y -+ depends on COMPAT && KEYS -+ - config PERSISTENT_KEYRINGS - bool "Enable register of persistent per-UID keyrings" - depends on KEYS -diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c -index c4acf17e9f5e..e40a2cba5002 100644 ---- a/sound/core/seq/seq_device.c -+++ b/sound/core/seq/seq_device.c -@@ -148,8 +148,10 @@ void snd_seq_device_load_drivers(void) - flush_work(&autoload_work); - } - EXPORT_SYMBOL(snd_seq_device_load_drivers); -+#define cancel_autoload_drivers() cancel_work_sync(&autoload_work) - #else - #define queue_autoload_drivers() /* NOP */ -+#define cancel_autoload_drivers() /* NOP */ - #endif - - /* -@@ -159,6 +161,7 @@ static int snd_seq_device_dev_free(struct snd_device *device) - { - struct snd_seq_device *dev = device->device_data; - -+ cancel_autoload_drivers(); - put_device(&dev->dev); - return 0; - } diff --git a/patch/kernel/rockchip-default/stowed/03-patch-4.4.99-100.patch b/patch/kernel/rockchip-default/stowed/03-patch-4.4.99-100.patch deleted file mode 100644 index e0c456c39..000000000 --- a/patch/kernel/rockchip-default/stowed/03-patch-4.4.99-100.patch +++ /dev/null @@ -1,2132 +0,0 @@ -diff --git a/Makefile b/Makefile -index 0b5d9e20eee2..91dd7832f499 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 99 -+SUBLEVEL = 100 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi -index d23e2524d694..be9c37e89be1 100644 ---- a/arch/arm/boot/dts/am33xx.dtsi -+++ b/arch/arm/boot/dts/am33xx.dtsi -@@ -142,10 +142,11 @@ - }; - - scm_conf: scm_conf@0 { -- compatible = "syscon"; -+ compatible = "syscon", "simple-bus"; - reg = <0x0 0x800>; - #address-cells = <1>; - #size-cells = <1>; -+ ranges = <0 0 0x800>; - - scm_clocks: clocks { - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/dm814x.dtsi b/arch/arm/boot/dts/dm814x.dtsi -index 7988b42e5764..c226c3d952d8 100644 ---- a/arch/arm/boot/dts/dm814x.dtsi -+++ b/arch/arm/boot/dts/dm814x.dtsi -@@ -138,7 +138,7 @@ - }; - - uart1: uart@20000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart1"; - reg = <0x20000 0x2000>; - clock-frequency = <48000000>; -@@ -148,7 +148,7 @@ - }; - - uart2: uart@22000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart2"; - reg = <0x22000 0x2000>; - clock-frequency = <48000000>; -@@ -158,7 +158,7 @@ - }; - - uart3: uart@24000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart3"; - reg = <0x24000 0x2000>; - clock-frequency = <48000000>; -@@ -189,10 +189,11 @@ - ranges = <0 0x160000 0x16d000>; - - scm_conf: scm_conf@0 { -- compatible = "syscon"; -+ compatible = "syscon", "simple-bus"; - reg = <0x0 0x800>; - #address-cells = <1>; - #size-cells = <1>; -+ ranges = <0 0 0x800>; - - scm_clocks: clocks { - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/dm816x.dtsi b/arch/arm/boot/dts/dm816x.dtsi -index eee636de4cd8..e526928e6e96 100644 ---- a/arch/arm/boot/dts/dm816x.dtsi -+++ b/arch/arm/boot/dts/dm816x.dtsi -@@ -347,7 +347,7 @@ - }; - - uart1: uart@48020000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart1"; - reg = <0x48020000 0x2000>; - clock-frequency = <48000000>; -@@ -357,7 +357,7 @@ - }; - - uart2: uart@48022000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart2"; - reg = <0x48022000 0x2000>; - clock-frequency = <48000000>; -@@ -367,7 +367,7 @@ - }; - - uart3: uart@48024000 { -- compatible = "ti,omap3-uart"; -+ compatible = "ti,am3352-uart", "ti,omap3-uart"; - ti,hwmods = "uart3"; - reg = <0x48024000 0x2000>; - clock-frequency = <48000000>; -diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c -index 6d685298690e..648d5fac9cbf 100644 ---- a/arch/arm/crypto/aesbs-glue.c -+++ b/arch/arm/crypto/aesbs-glue.c -@@ -357,7 +357,7 @@ static struct crypto_alg aesbs_algs[] = { { - }, { - .cra_name = "cbc(aes)", - .cra_driver_name = "cbc-aes-neonbs", -- .cra_priority = 300, -+ .cra_priority = 250, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_helper_ctx), -@@ -377,7 +377,7 @@ static struct crypto_alg aesbs_algs[] = { { - }, { - .cra_name = "ctr(aes)", - .cra_driver_name = "ctr-aes-neonbs", -- .cra_priority = 300, -+ .cra_priority = 250, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct async_helper_ctx), -@@ -397,7 +397,7 @@ static struct crypto_alg aesbs_algs[] = { { - }, { - .cra_name = "xts(aes)", - .cra_driver_name = "xts-aes-neonbs", -- .cra_priority = 300, -+ .cra_priority = 250, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct async_helper_ctx), -diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c -index 58144779dec4..1e6e09841707 100644 ---- a/arch/arm/mach-omap2/pdata-quirks.c -+++ b/arch/arm/mach-omap2/pdata-quirks.c -@@ -522,7 +522,6 @@ static void pdata_quirks_check(struct pdata_init *quirks) - if (of_machine_is_compatible(quirks->compatible)) { - if (quirks->fn) - quirks->fn(); -- break; - } - quirks++; - } -diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi -index 3c92d92278e5..a14a6bb31887 100644 ---- a/arch/arm64/boot/dts/broadcom/ns2.dtsi -+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi -@@ -30,6 +30,8 @@ - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -+/memreserve/ 0x81000000 0x00200000; -+ - #include - - /memreserve/ 0x84b00000 0x00000008; -diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h -index 7c26b28bf252..859cf7048347 100644 ---- a/arch/mips/include/asm/asm.h -+++ b/arch/mips/include/asm/asm.h -@@ -54,7 +54,8 @@ - .align 2; \ - .type symbol, @function; \ - .ent symbol, 0; \ --symbol: .frame sp, 0, ra -+symbol: .frame sp, 0, ra; \ -+ .insn - - /* - * NESTED - declare nested routine entry point -@@ -63,8 +64,9 @@ symbol: .frame sp, 0, ra - .globl symbol; \ - .align 2; \ - .type symbol, @function; \ -- .ent symbol, 0; \ --symbol: .frame sp, framesize, rpc -+ .ent symbol, 0; \ -+symbol: .frame sp, framesize, rpc; \ -+ .insn - - /* - * END - mark end of function -@@ -86,7 +88,7 @@ symbol: - #define FEXPORT(symbol) \ - .globl symbol; \ - .type symbol, @function; \ --symbol: -+symbol: .insn - - /* - * ABS - export absolute symbol -diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c -index 8acae316f26b..4f9f1ae49213 100644 ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -152,6 +152,35 @@ void __init detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_add - add_memory_region(start, size, BOOT_MEM_RAM); - } - -+bool __init memory_region_available(phys_addr_t start, phys_addr_t size) -+{ -+ int i; -+ bool in_ram = false, free = true; -+ -+ for (i = 0; i < boot_mem_map.nr_map; i++) { -+ phys_addr_t start_, end_; -+ -+ start_ = boot_mem_map.map[i].addr; -+ end_ = boot_mem_map.map[i].addr + boot_mem_map.map[i].size; -+ -+ switch (boot_mem_map.map[i].type) { -+ case BOOT_MEM_RAM: -+ if (start >= start_ && start + size <= end_) -+ in_ram = true; -+ break; -+ case BOOT_MEM_RESERVED: -+ if ((start >= start_ && start < end_) || -+ (start < start_ && start + size >= start_)) -+ free = false; -+ break; -+ default: -+ continue; -+ } -+ } -+ -+ return in_ram && free; -+} -+ - static void __init print_memory_map(void) - { - int i; -@@ -300,11 +329,19 @@ static void __init bootmem_init(void) - - #else /* !CONFIG_SGI_IP27 */ - -+static unsigned long __init bootmap_bytes(unsigned long pages) -+{ -+ unsigned long bytes = DIV_ROUND_UP(pages, 8); -+ -+ return ALIGN(bytes, sizeof(long)); -+} -+ - static void __init bootmem_init(void) - { - unsigned long reserved_end; - unsigned long mapstart = ~0UL; - unsigned long bootmap_size; -+ bool bootmap_valid = false; - int i; - - /* -@@ -385,11 +422,42 @@ static void __init bootmem_init(void) - #endif - - /* -- * Initialize the boot-time allocator with low memory only. -+ * check that mapstart doesn't overlap with any of -+ * memory regions that have been reserved through eg. DTB - */ -- bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, -- min_low_pfn, max_low_pfn); -+ bootmap_size = bootmap_bytes(max_low_pfn - min_low_pfn); -+ -+ bootmap_valid = memory_region_available(PFN_PHYS(mapstart), -+ bootmap_size); -+ for (i = 0; i < boot_mem_map.nr_map && !bootmap_valid; i++) { -+ unsigned long mapstart_addr; -+ -+ switch (boot_mem_map.map[i].type) { -+ case BOOT_MEM_RESERVED: -+ mapstart_addr = PFN_ALIGN(boot_mem_map.map[i].addr + -+ boot_mem_map.map[i].size); -+ if (PHYS_PFN(mapstart_addr) < mapstart) -+ break; -+ -+ bootmap_valid = memory_region_available(mapstart_addr, -+ bootmap_size); -+ if (bootmap_valid) -+ mapstart = PHYS_PFN(mapstart_addr); -+ break; -+ default: -+ break; -+ } -+ } - -+ if (!bootmap_valid) -+ panic("No memory area to place a bootmap bitmap"); -+ -+ /* -+ * Initialize the boot-time allocator with low memory only. -+ */ -+ if (bootmap_size != init_bootmem_node(NODE_DATA(0), mapstart, -+ min_low_pfn, max_low_pfn)) -+ panic("Unexpected memory size required for bootmap"); - - for (i = 0; i < boot_mem_map.nr_map; i++) { - unsigned long start, end; -@@ -438,6 +506,10 @@ static void __init bootmem_init(void) - continue; - default: - /* Not usable memory */ -+ if (start > min_low_pfn && end < max_low_pfn) -+ reserve_bootmem(boot_mem_map.map[i].addr, -+ boot_mem_map.map[i].size, -+ BOOTMEM_DEFAULT); - continue; - } - -diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c -index 3660dc67d544..f4961bc9a61d 100644 ---- a/arch/mips/netlogic/common/irq.c -+++ b/arch/mips/netlogic/common/irq.c -@@ -275,7 +275,7 @@ asmlinkage void plat_irq_dispatch(void) - do_IRQ(nlm_irq_to_xirq(node, i)); - } - --#ifdef CONFIG_OF -+#ifdef CONFIG_CPU_XLP - static const struct irq_domain_ops xlp_pic_irq_domain_ops = { - .xlate = irq_domain_xlate_onetwocell, - }; -@@ -348,7 +348,7 @@ void __init arch_init_irq(void) - #if defined(CONFIG_CPU_XLR) - nlm_setup_fmn_irq(); - #endif --#if defined(CONFIG_OF) -+#ifdef CONFIG_CPU_XLP - of_irq_init(xlp_pic_irq_ids); - #endif - } -diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h -index 19d14ac23ef9..fc3c7e49c8e4 100644 ---- a/arch/x86/include/asm/kvm_emulate.h -+++ b/arch/x86/include/asm/kvm_emulate.h -@@ -296,6 +296,7 @@ struct x86_emulate_ctxt { - - bool perm_ok; /* do not check permissions if true */ - bool ud; /* inject an #UD if host doesn't support insn */ -+ bool tf; /* TF value before instruction (after for syscall/sysret) */ - - bool have_exception; - struct x86_exception exception; -diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c -index 04b2f3cad7ba..684edebb4a0c 100644 ---- a/arch/x86/kvm/emulate.c -+++ b/arch/x86/kvm/emulate.c -@@ -2726,6 +2726,7 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt) - ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF); - } - -+ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; - return X86EMUL_CONTINUE; - } - -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 8e526c6fd784..3ffd5900da5b 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -5095,6 +5095,8 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu) - kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); - - ctxt->eflags = kvm_get_rflags(vcpu); -+ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; -+ - ctxt->eip = kvm_rip_read(vcpu); - ctxt->mode = (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL : - (ctxt->eflags & X86_EFLAGS_VM) ? X86EMUL_MODE_VM86 : -@@ -5315,37 +5317,26 @@ static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7, - return dr6; - } - --static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r) -+static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r) - { - struct kvm_run *kvm_run = vcpu->run; - -- /* -- * rflags is the old, "raw" value of the flags. The new value has -- * not been saved yet. -- * -- * This is correct even for TF set by the guest, because "the -- * processor will not generate this exception after the instruction -- * that sets the TF flag". -- */ -- if (unlikely(rflags & X86_EFLAGS_TF)) { -- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { -- kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | -- DR6_RTM; -- kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; -- kvm_run->debug.arch.exception = DB_VECTOR; -- kvm_run->exit_reason = KVM_EXIT_DEBUG; -- *r = EMULATE_USER_EXIT; -- } else { -- vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; -- /* -- * "Certain debug exceptions may clear bit 0-3. The -- * remaining contents of the DR6 register are never -- * cleared by the processor". -- */ -- vcpu->arch.dr6 &= ~15; -- vcpu->arch.dr6 |= DR6_BS | DR6_RTM; -- kvm_queue_exception(vcpu, DB_VECTOR); -- } -+ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { -+ kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | DR6_RTM; -+ kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; -+ kvm_run->debug.arch.exception = DB_VECTOR; -+ kvm_run->exit_reason = KVM_EXIT_DEBUG; -+ *r = EMULATE_USER_EXIT; -+ } else { -+ vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; -+ /* -+ * "Certain debug exceptions may clear bit 0-3. The -+ * remaining contents of the DR6 register are never -+ * cleared by the processor". -+ */ -+ vcpu->arch.dr6 &= ~15; -+ vcpu->arch.dr6 |= DR6_BS | DR6_RTM; -+ kvm_queue_exception(vcpu, DB_VECTOR); - } - } - -@@ -5500,8 +5491,9 @@ restart: - toggle_interruptibility(vcpu, ctxt->interruptibility); - vcpu->arch.emulate_regs_need_sync_to_vcpu = false; - kvm_rip_write(vcpu, ctxt->eip); -- if (r == EMULATE_DONE) -- kvm_vcpu_check_singlestep(vcpu, rflags, &r); -+ if (r == EMULATE_DONE && -+ (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP))) -+ kvm_vcpu_do_singlestep(vcpu, &r); - if (!ctxt->have_exception || - exception_type(ctxt->exception.vector) == EXCPT_TRAP) - __kvm_set_rflags(vcpu, ctxt->eflags); -diff --git a/crypto/Kconfig b/crypto/Kconfig -index 617bf4a7da56..7240821137fd 100644 ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -343,7 +343,6 @@ config CRYPTO_XTS - select CRYPTO_BLKCIPHER - select CRYPTO_MANAGER - select CRYPTO_GF128MUL -- select CRYPTO_ECB - help - XTS: IEEE1619/D16 narrow block cipher use with aes-xts-plain, - key size 256, 384 or 512 bits. This implementation currently -diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig -index 6aaa3f81755b..c2ba811993d4 100644 ---- a/drivers/ata/Kconfig -+++ b/drivers/ata/Kconfig -@@ -272,6 +272,7 @@ config SATA_SX4 - - config ATA_BMDMA - bool "ATA BMDMA support" -+ depends on HAS_DMA - default y - help - This option adds support for SFF ATA controllers with BMDMA -@@ -318,6 +319,7 @@ config SATA_DWC_VDEBUG - - config SATA_HIGHBANK - tristate "Calxeda Highbank SATA support" -+ depends on HAS_DMA - depends on ARCH_HIGHBANK || COMPILE_TEST - help - This option enables support for the Calxeda Highbank SoC's -@@ -327,6 +329,7 @@ config SATA_HIGHBANK - - config SATA_MV - tristate "Marvell SATA support" -+ depends on HAS_DMA - depends on PCI || ARCH_DOVE || ARCH_MV78XX0 || \ - ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST - select GENERIC_PHY -diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c -index 33e23a7a691f..a295ad6a1674 100644 ---- a/drivers/block/xen-blkback/blkback.c -+++ b/drivers/block/xen-blkback/blkback.c -@@ -1407,33 +1407,34 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, - static void make_response(struct xen_blkif *blkif, u64 id, - unsigned short op, int st) - { -- struct blkif_response resp; -+ struct blkif_response *resp; - unsigned long flags; - union blkif_back_rings *blk_rings = &blkif->blk_rings; - int notify; - -- resp.id = id; -- resp.operation = op; -- resp.status = st; -- - spin_lock_irqsave(&blkif->blk_ring_lock, flags); - /* Place on the response ring for the relevant domain. */ - switch (blkif->blk_protocol) { - case BLKIF_PROTOCOL_NATIVE: -- memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt), -- &resp, sizeof(resp)); -+ resp = RING_GET_RESPONSE(&blk_rings->native, -+ blk_rings->native.rsp_prod_pvt); - break; - case BLKIF_PROTOCOL_X86_32: -- memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt), -- &resp, sizeof(resp)); -+ resp = RING_GET_RESPONSE(&blk_rings->x86_32, -+ blk_rings->x86_32.rsp_prod_pvt); - break; - case BLKIF_PROTOCOL_X86_64: -- memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt), -- &resp, sizeof(resp)); -+ resp = RING_GET_RESPONSE(&blk_rings->x86_64, -+ blk_rings->x86_64.rsp_prod_pvt); - break; - default: - BUG(); - } -+ -+ resp->id = id; -+ resp->operation = op; -+ resp->status = st; -+ - blk_rings->common.rsp_prod_pvt++; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); - spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); -diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h -index c929ae22764c..04cfee719334 100644 ---- a/drivers/block/xen-blkback/common.h -+++ b/drivers/block/xen-blkback/common.h -@@ -74,9 +74,8 @@ extern unsigned int xen_blkif_max_ring_order; - struct blkif_common_request { - char dummy; - }; --struct blkif_common_response { -- char dummy; --}; -+ -+/* i386 protocol version */ - - struct blkif_x86_32_request_rw { - uint8_t nr_segments; /* number of segments */ -@@ -128,14 +127,6 @@ struct blkif_x86_32_request { - } u; - } __attribute__((__packed__)); - --/* i386 protocol version */ --#pragma pack(push, 4) --struct blkif_x86_32_response { -- uint64_t id; /* copied from request */ -- uint8_t operation; /* copied from request */ -- int16_t status; /* BLKIF_RSP_??? */ --}; --#pragma pack(pop) - /* x86_64 protocol version */ - - struct blkif_x86_64_request_rw { -@@ -192,18 +183,12 @@ struct blkif_x86_64_request { - } u; - } __attribute__((__packed__)); - --struct blkif_x86_64_response { -- uint64_t __attribute__((__aligned__(8))) id; -- uint8_t operation; /* copied from request */ -- int16_t status; /* BLKIF_RSP_??? */ --}; -- - DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, -- struct blkif_common_response); -+ struct blkif_response); - DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, -- struct blkif_x86_32_response); -+ struct blkif_response __packed); - DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, -- struct blkif_x86_64_response); -+ struct blkif_response); - - union blkif_back_rings { - struct blkif_back_ring native; -diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c -index 7bb8055bd10c..1ccad79ce77c 100644 ---- a/drivers/bluetooth/btusb.c -+++ b/drivers/bluetooth/btusb.c -@@ -2969,6 +2969,12 @@ 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. -+ */ -+ set_bit(BTUSB_RESET_RESUME, &data->flags); - } - - #ifdef CONFIG_BT_HCIBTUSB_RTL -diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c -index b8576fd6bd0e..1c7568c0055a 100644 ---- a/drivers/dma/dmatest.c -+++ b/drivers/dma/dmatest.c -@@ -634,6 +634,7 @@ static int dmatest_func(void *data) - * free it this time?" dancing. For now, just - * leave it dangling. - */ -+ WARN(1, "dmatest: Kernel stack may be corrupted!!\n"); - dmaengine_unmap_put(um); - result("test timed out", total_tests, src_off, dst_off, - len, 0); -diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c -index 93c30a885740..aa2f6bb82b32 100644 ---- a/drivers/extcon/extcon-palmas.c -+++ b/drivers/extcon/extcon-palmas.c -@@ -190,6 +190,11 @@ static int palmas_usb_probe(struct platform_device *pdev) - struct palmas_usb *palmas_usb; - int status; - -+ if (!palmas) { -+ dev_err(&pdev->dev, "failed to get valid parent\n"); -+ return -EINVAL; -+ } -+ - palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); - if (!palmas_usb) - return -ENOMEM; -diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c -index b1a0f5656175..44df959cbadb 100644 ---- a/drivers/gpu/drm/mgag200/mgag200_main.c -+++ b/drivers/gpu/drm/mgag200/mgag200_main.c -@@ -145,6 +145,8 @@ static int mga_vram_init(struct mga_device *mdev) - } - - mem = pci_iomap(mdev->dev->pdev, 0, 0); -+ if (!mem) -+ return -ENOMEM; - - mdev->mc.vram_size = mga_probe_vram(mdev, mem); - -diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c -index d56630c60039..117a2f52fb4e 100644 ---- a/drivers/gpu/drm/sti/sti_vtg.c -+++ b/drivers/gpu/drm/sti/sti_vtg.c -@@ -346,6 +346,10 @@ static int vtg_probe(struct platform_device *pdev) - return -ENOMEM; - } - vtg->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); -+ if (!vtg->regs) { -+ DRM_ERROR("failed to remap I/O memory\n"); -+ return -ENOMEM; -+ } - - np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0); - if (np) { -diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c -index eb9e7feb9b13..7a16e9ea041c 100644 ---- a/drivers/media/rc/imon.c -+++ b/drivers/media/rc/imon.c -@@ -2419,6 +2419,11 @@ static int imon_probe(struct usb_interface *interface, - mutex_lock(&driver_lock); - - first_if = usb_ifnum_to_if(usbdev, 0); -+ if (!first_if) { -+ ret = -ENODEV; -+ goto fail; -+ } -+ - first_if_ctx = usb_get_intfdata(first_if); - - if (ifnum == 0) { -diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c -index 7ed49646a699..7df0707a0455 100644 ---- a/drivers/media/usb/dvb-usb/dib0700_devices.c -+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c -@@ -292,7 +292,7 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) - stk7700d_dib7000p_mt2266_config) - != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - } -@@ -326,7 +326,7 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) - stk7700d_dib7000p_mt2266_config) - != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - } -@@ -479,7 +479,7 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) - &stk7700ph_dib7700_xc3028_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -1010,7 +1010,7 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) - &dib7070p_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -1068,7 +1068,7 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) - &dib7770p_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -3036,7 +3036,7 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) - - if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); -@@ -3089,7 +3089,7 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) - /* initialize IC 0 */ - if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -3119,7 +3119,7 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) - i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); - if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -3194,7 +3194,7 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) - 1, 0x10, &tfe7790p_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, -@@ -3289,7 +3289,7 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) - stk7070pd_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -@@ -3364,7 +3364,7 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap) - stk7070pd_dib7000p_config) != 0) { - err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", - __func__); -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - } -@@ -3600,7 +3600,7 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) - - if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) { - /* Demodulator not found for some reason? */ -- dvb_detach(&state->dib7000p_ops); -+ dvb_detach(state->dib7000p_ops.set_wbd_ref); - return -ENODEV; - } - -diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c -index af09a1b272e6..6a2d1454befe 100644 ---- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c -+++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c -@@ -2002,9 +2002,10 @@ static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw, - * function can also be used to respond to an error as the connection - * resetting would also be a means of dealing with errors. - **/ --static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, -- struct fm10k_mbx_info *mbx) -+static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, -+ struct fm10k_mbx_info *mbx) - { -+ s32 err = 0; - const enum fm10k_mbx_state state = mbx->state; - - switch (state) { -@@ -2017,6 +2018,7 @@ static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, - case FM10K_STATE_OPEN: - /* flush any incomplete work */ - fm10k_sm_mbx_connect_reset(mbx); -+ err = FM10K_ERR_RESET_REQUESTED; - break; - case FM10K_STATE_CONNECT: - /* Update remote value to match local value */ -@@ -2026,6 +2028,8 @@ static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw, - } - - fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail); -+ -+ return err; - } - - /** -@@ -2106,7 +2110,7 @@ static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw, - - switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) { - case 0: -- fm10k_sm_mbx_process_reset(hw, mbx); -+ err = fm10k_sm_mbx_process_reset(hw, mbx); - break; - case FM10K_SM_MBX_VERSION: - err = fm10k_sm_mbx_process_version_1(hw, mbx); -diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c -index 7f3fb51bc37b..06f35700840b 100644 ---- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c -+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c -@@ -1072,6 +1072,7 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) - struct fm10k_hw *hw = &interface->hw; - struct fm10k_mbx_info *mbx = &hw->mbx; - u32 eicr; -+ s32 err = 0; - - /* unmask any set bits related to this interrupt */ - eicr = fm10k_read_reg(hw, FM10K_EICR); -@@ -1087,12 +1088,15 @@ static irqreturn_t fm10k_msix_mbx_pf(int __always_unused irq, void *data) - - /* service mailboxes */ - if (fm10k_mbx_trylock(interface)) { -- mbx->ops.process(hw, mbx); -+ err = mbx->ops.process(hw, mbx); - /* handle VFLRE events */ - fm10k_iov_event(interface); - fm10k_mbx_unlock(interface); - } - -+ if (err == FM10K_ERR_RESET_REQUESTED) -+ interface->flags |= FM10K_FLAG_RESET_REQUESTED; -+ - /* if switch toggled state we should reset GLORTs */ - if (eicr & FM10K_EICR_SWITCHNOTREADY) { - /* force link down for at least 4 seconds */ -diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c -index 97bf0c3d5c69..f3f3b95d5512 100644 ---- a/drivers/net/ethernet/intel/igb/e1000_82575.c -+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c -@@ -223,6 +223,17 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw) - hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >> - E1000_STATUS_FUNC_SHIFT; - -+ /* Make sure the PHY is in a good state. Several people have reported -+ * firmware leaving the PHY's page select register set to something -+ * other than the default of zero, which causes the PHY ID read to -+ * access something other than the intended register. -+ */ -+ ret_val = hw->phy.ops.reset(hw); -+ if (ret_val) { -+ hw_dbg("Error resetting the PHY.\n"); -+ goto out; -+ } -+ - /* Set phy->phy_addr and phy->id. */ - ret_val = igb_get_phy_id_82575(hw); - if (ret_val) -diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c -index 29f59c76878a..851225b5dc0f 100644 ---- a/drivers/net/ethernet/intel/igb/e1000_i210.c -+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c -@@ -699,9 +699,9 @@ static s32 igb_update_flash_i210(struct e1000_hw *hw) - - ret_val = igb_pool_flash_update_done_i210(hw); - if (ret_val) -- hw_dbg("Flash update complete\n"); -- else - hw_dbg("Flash update time out\n"); -+ else -+ hw_dbg("Flash update complete\n"); - - out: - return ret_val; -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index a481ea64e287..ff6e57d788eb 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -3172,7 +3172,9 @@ static int __igb_close(struct net_device *netdev, bool suspending) - - static int igb_close(struct net_device *netdev) - { -- return __igb_close(netdev, false); -+ if (netif_device_present(netdev)) -+ return __igb_close(netdev, false); -+ return 0; - } - - /** -@@ -7325,12 +7327,14 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, - int retval = 0; - #endif - -+ rtnl_lock(); - netif_device_detach(netdev); - - if (netif_running(netdev)) - __igb_close(netdev, true); - - igb_clear_interrupt_scheme(adapter); -+ rtnl_unlock(); - - #ifdef CONFIG_PM - retval = pci_save_state(pdev); -@@ -7450,16 +7454,15 @@ static int igb_resume(struct device *dev) - - wr32(E1000_WUS, ~0); - -- if (netdev->flags & IFF_UP) { -- rtnl_lock(); -+ rtnl_lock(); -+ if (!err && netif_running(netdev)) - err = __igb_open(netdev, true); -- rtnl_unlock(); -- if (err) -- return err; -- } - -- netif_device_attach(netdev); -- return 0; -+ if (!err) -+ netif_device_attach(netdev); -+ rtnl_unlock(); -+ -+ return err; - } - - static int igb_runtime_idle(struct device *dev) -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c -index f3168bcc7d87..f0de09db8283 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c -@@ -307,6 +307,7 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) - ixgbe_cache_ring_rss(adapter); - } - -+#define IXGBE_RSS_64Q_MASK 0x3F - #define IXGBE_RSS_16Q_MASK 0xF - #define IXGBE_RSS_8Q_MASK 0x7 - #define IXGBE_RSS_4Q_MASK 0x3 -@@ -602,6 +603,7 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) - **/ - static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) - { -+ struct ixgbe_hw *hw = &adapter->hw; - struct ixgbe_ring_feature *f; - u16 rss_i; - -@@ -610,7 +612,11 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter) - rss_i = f->limit; - - f->indices = rss_i; -- f->mask = IXGBE_RSS_16Q_MASK; -+ -+ if (hw->mac.type < ixgbe_mac_X550) -+ f->mask = IXGBE_RSS_16Q_MASK; -+ else -+ f->mask = IXGBE_RSS_64Q_MASK; - - /* disable ATR by default, it will be configured below */ - adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -index cd9b284bc83b..83645d8503d4 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -@@ -5878,7 +5878,8 @@ static int ixgbe_close(struct net_device *netdev) - - ixgbe_ptp_stop(adapter); - -- ixgbe_close_suspend(adapter); -+ if (netif_device_present(netdev)) -+ ixgbe_close_suspend(adapter); - - ixgbe_fdir_filter_exit(adapter); - -@@ -5923,14 +5924,12 @@ static int ixgbe_resume(struct pci_dev *pdev) - if (!err && netif_running(netdev)) - err = ixgbe_open(netdev); - -- rtnl_unlock(); -- -- if (err) -- return err; - -- netif_device_attach(netdev); -+ if (!err) -+ netif_device_attach(netdev); -+ rtnl_unlock(); - -- return 0; -+ return err; - } - #endif /* CONFIG_PM */ - -@@ -5945,14 +5944,14 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) - int retval = 0; - #endif - -+ rtnl_lock(); - netif_device_detach(netdev); - -- rtnl_lock(); - if (netif_running(netdev)) - ixgbe_close_suspend(adapter); -- rtnl_unlock(); - - ixgbe_clear_interrupt_scheme(adapter); -+ rtnl_unlock(); - - #ifdef CONFIG_PM - retval = pci_save_state(pdev); -@@ -9221,7 +9220,7 @@ skip_bad_vf_detection: - } - - if (netif_running(netdev)) -- ixgbe_down(adapter); -+ ixgbe_close_suspend(adapter); - - if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state)) - pci_disable_device(pdev); -@@ -9291,10 +9290,12 @@ static void ixgbe_io_resume(struct pci_dev *pdev) - } - - #endif -+ rtnl_lock(); - if (netif_running(netdev)) -- ixgbe_up(adapter); -+ ixgbe_open(netdev); - - netif_device_attach(netdev); -+ rtnl_unlock(); - } - - static const struct pci_error_handlers ixgbe_err_handler = { -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c -index fb8673d63806..48d97cb730d8 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c -@@ -113,7 +113,7 @@ static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val, bool lock) - { - u32 swfw_mask = hw->phy.phy_semaphore_mask; -- int max_retry = 10; -+ int max_retry = 3; - int retry = 0; - u8 csum_byte; - u8 high_bits; -@@ -1764,6 +1764,8 @@ static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, - u32 swfw_mask = hw->phy.phy_semaphore_mask; - bool nack = true; - -+ if (hw->mac.type >= ixgbe_mac_X550) -+ max_retry = 3; - if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr)) - max_retry = IXGBE_SFP_DETECT_RETRIES; - -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -index ebe0ac950b14..31f864fb30c1 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c -@@ -1643,8 +1643,6 @@ static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, - return status; - - reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; -- reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ | -- IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC); - reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | - IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); - -diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c -index 8c408aa2f208..f9343bee1de3 100644 ---- a/drivers/net/usb/cdc_ether.c -+++ b/drivers/net/usb/cdc_ether.c -@@ -221,7 +221,7 @@ skip: - goto bad_desc; - } - -- if (header.usb_cdc_ether_desc) { -+ if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) { - dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize); - /* because of Zaurus, we may be ignoring the host - * side link address we were given. -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index 958af3b1af7f..e325ca3ad565 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -262,7 +262,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) - } - - /* errors aren't fatal - we can live with the dynamic address */ -- if (cdc_ether) { -+ if (cdc_ether && cdc_ether->wMaxSegmentSize) { - dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize); - usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress); - } -diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c -index f6446d759d7f..4639dac64e7f 100644 ---- a/drivers/scsi/lpfc/lpfc_attr.c -+++ b/drivers/scsi/lpfc/lpfc_attr.c -@@ -5147,6 +5147,19 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) - * Dynamic FC Host Attributes Support - */ - -+/** -+ * lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host -+ * @shost: kernel scsi host pointer. -+ **/ -+static void -+lpfc_get_host_symbolic_name(struct Scsi_Host *shost) -+{ -+ struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; -+ -+ lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost), -+ sizeof fc_host_symbolic_name(shost)); -+} -+ - /** - * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id - * @shost: kernel scsi host pointer. -@@ -5684,6 +5697,8 @@ struct fc_function_template lpfc_transport_functions = { - .show_host_supported_fc4s = 1, - .show_host_supported_speeds = 1, - .show_host_maxframe_size = 1, -+ -+ .get_host_symbolic_name = lpfc_get_host_symbolic_name, - .show_host_symbolic_name = 1, - - /* dynamic attributes the driver supports */ -@@ -5751,6 +5766,8 @@ struct fc_function_template lpfc_vport_transport_functions = { - .show_host_supported_fc4s = 1, - .show_host_supported_speeds = 1, - .show_host_maxframe_size = 1, -+ -+ .get_host_symbolic_name = lpfc_get_host_symbolic_name, - .show_host_symbolic_name = 1, - - /* dynamic attributes the driver supports */ -diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c -index c74f74ab981c..d278362448ca 100644 ---- a/drivers/scsi/lpfc/lpfc_els.c -+++ b/drivers/scsi/lpfc/lpfc_els.c -@@ -1982,6 +1982,9 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) - if (sp->cmn.fcphHigh < FC_PH3) - sp->cmn.fcphHigh = FC_PH3; - -+ sp->cmn.valid_vendor_ver_level = 0; -+ memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); -+ - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "Issue PLOGI: did:x%x", - did, 0, 0); -@@ -3966,6 +3969,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, - } else { - memcpy(pcmd, &vport->fc_sparam, - sizeof(struct serv_parm)); -+ -+ sp->cmn.valid_vendor_ver_level = 0; -+ memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); - } - - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, -diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h -index 2cce88e967ce..a8ad97300177 100644 ---- a/drivers/scsi/lpfc/lpfc_hw.h -+++ b/drivers/scsi/lpfc/lpfc_hw.h -@@ -360,6 +360,12 @@ struct csp { - * Word 1 Bit 30 in PLOGI request is random offset - */ - #define virtual_fabric_support randomOffset /* Word 1, bit 30 */ -+/* -+ * Word 1 Bit 29 in common service parameter is overloaded. -+ * Word 1 Bit 29 in FLOGI response is multiple NPort assignment -+ * Word 1 Bit 29 in FLOGI/PLOGI request is Valid Vendor Version Level -+ */ -+#define valid_vendor_ver_level response_multiple_NPort /* Word 1, bit 29 */ - #ifdef __BIG_ENDIAN_BITFIELD - uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ - uint16_t randomOffset:1; /* FC Word 1, bit 30 */ -diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c -index 38e90d9c2ced..8379fbbc60db 100644 ---- a/drivers/scsi/lpfc/lpfc_sli.c -+++ b/drivers/scsi/lpfc/lpfc_sli.c -@@ -118,6 +118,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) - if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) - bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); - lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); -+ /* ensure WQE bcopy flushed before doorbell write */ -+ wmb(); - - /* Update the host index before invoking device */ - host_index = q->host_index; -@@ -9805,6 +9807,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - iabt->ulpCommand = CMD_CLOSE_XRI_CN; - - abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; -+ abtsiocbp->vport = vport; - - lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0339 Abort xri x%x, original iotag x%x, " -diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c -index 769012663a8f..861c57bc4520 100644 ---- a/drivers/scsi/lpfc/lpfc_vport.c -+++ b/drivers/scsi/lpfc/lpfc_vport.c -@@ -528,6 +528,12 @@ enable_vport(struct fc_vport *fc_vport) - - spin_lock_irq(shost->host_lock); - vport->load_flag |= FC_LOADING; -+ if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) { -+ spin_unlock_irq(shost->host_lock); -+ lpfc_issue_init_vpi(vport); -+ goto out; -+ } -+ - vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; - spin_unlock_irq(shost->host_lock); - -@@ -548,6 +554,8 @@ enable_vport(struct fc_vport *fc_vport) - } else { - lpfc_vport_set_state(vport, FC_VPORT_FAILED); - } -+ -+out: - lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, - "1827 Vport Enabled.\n"); - return VPORT_OK; -diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c -index 4f38d008bfb4..4b82c3765e01 100644 ---- a/drivers/scsi/ufs/ufs-qcom.c -+++ b/drivers/scsi/ufs/ufs-qcom.c -@@ -1552,6 +1552,7 @@ static const struct of_device_id ufs_qcom_of_match[] = { - { .compatible = "qcom,ufshc"}, - {}, - }; -+MODULE_DEVICE_TABLE(of, ufs_qcom_of_match); - - static const struct dev_pm_ops ufs_qcom_pm_ops = { - .suspend = ufshcd_pltfrm_suspend, -diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c -index 85cd2564c157..0c2482ec7d21 100644 ---- a/drivers/scsi/ufs/ufshcd.c -+++ b/drivers/scsi/ufs/ufshcd.c -@@ -3340,18 +3340,25 @@ out: - } - - /** -- * ufshcd_force_reset_auto_bkops - force enable of auto bkops -+ * ufshcd_force_reset_auto_bkops - force reset auto bkops state - * @hba: per adapter instance - * - * After a device reset the device may toggle the BKOPS_EN flag - * to default value. The s/w tracking variables should be updated -- * as well. Do this by forcing enable of auto bkops. -+ * as well. This function would change the auto-bkops state based on -+ * UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND. - */ --static void ufshcd_force_reset_auto_bkops(struct ufs_hba *hba) -+static void ufshcd_force_reset_auto_bkops(struct ufs_hba *hba) - { -- hba->auto_bkops_enabled = false; -- hba->ee_ctrl_mask |= MASK_EE_URGENT_BKOPS; -- ufshcd_enable_auto_bkops(hba); -+ if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) { -+ hba->auto_bkops_enabled = false; -+ hba->ee_ctrl_mask |= MASK_EE_URGENT_BKOPS; -+ ufshcd_enable_auto_bkops(hba); -+ } else { -+ hba->auto_bkops_enabled = true; -+ hba->ee_ctrl_mask &= ~MASK_EE_URGENT_BKOPS; -+ ufshcd_disable_auto_bkops(hba); -+ } - } - - static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32 *status) -@@ -5149,11 +5156,15 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) - goto set_old_link_state; - } - -- /* -- * If BKOPs operations are urgently needed at this moment then -- * keep auto-bkops enabled or else disable it. -- */ -- ufshcd_urgent_bkops(hba); -+ if (ufshcd_keep_autobkops_enabled_except_suspend(hba)) -+ ufshcd_enable_auto_bkops(hba); -+ else -+ /* -+ * If BKOPs operations are urgently needed at this moment then -+ * keep auto-bkops enabled or else disable it. -+ */ -+ ufshcd_urgent_bkops(hba); -+ - hba->clk_gating.is_suspended = false; - - if (ufshcd_is_clkscaling_enabled(hba)) -diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h -index 2570d9477b37..bb02100ab2dc 100644 ---- a/drivers/scsi/ufs/ufshcd.h -+++ b/drivers/scsi/ufs/ufshcd.h -@@ -528,6 +528,14 @@ struct ufs_hba { - * CAUTION: Enabling this might reduce overall UFS throughput. - */ - #define UFSHCD_CAP_INTR_AGGR (1 << 4) -+ /* -+ * This capability allows the device auto-bkops to be always enabled -+ * except during suspend (both runtime and suspend). -+ * Enabling this capability means that device will always be allowed -+ * to do background operation when it's active but it might degrade -+ * the performance of ongoing read/write operations. -+ */ -+#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) - - struct devfreq *devfreq; - struct ufs_clk_scaling clk_scaling; -@@ -623,6 +631,11 @@ static inline void *ufshcd_get_variant(struct ufs_hba *hba) - BUG_ON(!hba); - return hba->priv; - } -+static inline bool ufshcd_keep_autobkops_enabled_except_suspend( -+ struct ufs_hba *hba) -+{ -+ return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND; -+} - - extern int ufshcd_runtime_suspend(struct ufs_hba *hba); - extern int ufshcd_runtime_resume(struct ufs_hba *hba); -diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h -index 971bf457f32d..e75a386344e4 100644 ---- a/drivers/staging/rtl8188eu/include/rtw_debug.h -+++ b/drivers/staging/rtl8188eu/include/rtw_debug.h -@@ -75,7 +75,7 @@ extern u32 GlobalDebugLevel; - #define DBG_88E_LEVEL(_level, fmt, arg...) \ - do { \ - if (_level <= GlobalDebugLevel) \ -- pr_info(DRIVER_PREFIX"ERROR " fmt, ##arg); \ -+ pr_info(DRIVER_PREFIX fmt, ##arg); \ - } while (0) - - #define DBG_88E(...) \ -diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c -index edfc6805e012..2b348439242f 100644 ---- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c -+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c -@@ -199,7 +199,7 @@ static inline char *translate_scan(struct _adapter *padapter, - iwe.cmd = SIOCGIWMODE; - memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs), - 2); -- cap = le16_to_cpu(cap); -+ le16_to_cpus(&cap); - if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) { - if (cap & WLAN_CAPABILITY_BSS) - iwe.u.mode = (u32)IW_MODE_MASTER; -diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c -index 873ba02d59e6..f4c3a37e00ba 100644 ---- a/drivers/usb/core/devio.c -+++ b/drivers/usb/core/devio.c -@@ -1653,6 +1653,18 @@ static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg) - return 0; - } - -+static void compute_isochronous_actual_length(struct urb *urb) -+{ -+ unsigned int i; -+ -+ if (urb->number_of_packets > 0) { -+ urb->actual_length = 0; -+ for (i = 0; i < urb->number_of_packets; i++) -+ urb->actual_length += -+ urb->iso_frame_desc[i].actual_length; -+ } -+} -+ - static int processcompl(struct async *as, void __user * __user *arg) - { - struct urb *urb = as->urb; -@@ -1660,6 +1672,7 @@ static int processcompl(struct async *as, void __user * __user *arg) - void __user *addr = as->userurb; - unsigned int i; - -+ compute_isochronous_actual_length(urb); - if (as->userbuffer && urb->actual_length) { - if (copy_urb_data_to_user(as->userbuffer, urb)) - goto err_out; -@@ -1829,6 +1842,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) - void __user *addr = as->userurb; - unsigned int i; - -+ compute_isochronous_actual_length(urb); - if (as->userbuffer && urb->actual_length) { - if (copy_urb_data_to_user(as->userbuffer, urb)) - return -EFAULT; -diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c -index a6aaf2f193a4..37c418e581fb 100644 ---- a/drivers/usb/core/quirks.c -+++ b/drivers/usb/core/quirks.c -@@ -221,6 +221,9 @@ static const struct usb_device_id usb_quirk_list[] = { - /* Corsair Strafe RGB */ - { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, - -+ /* Corsair K70 LUX */ -+ { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, -+ - /* MIDI keyboard WORLDE MINI */ - { USB_DEVICE(0x1c75, 0x0204), .driver_info = - USB_QUIRK_CONFIG_INTF_STRINGS }, -diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c -index 37d0e8cc7af6..2220c1b9df10 100644 ---- a/drivers/usb/serial/garmin_gps.c -+++ b/drivers/usb/serial/garmin_gps.c -@@ -138,6 +138,7 @@ struct garmin_data { - __u8 privpkt[4*6]; - spinlock_t lock; - struct list_head pktlist; -+ struct usb_anchor write_urbs; - }; - - -@@ -906,13 +907,19 @@ static int garmin_init_session(struct usb_serial_port *port) - sizeof(GARMIN_START_SESSION_REQ), 0); - - if (status < 0) -- break; -+ goto err_kill_urbs; - } - - if (status > 0) - status = 0; - } - -+ return status; -+ -+err_kill_urbs: -+ usb_kill_anchored_urbs(&garmin_data_p->write_urbs); -+ usb_kill_urb(port->interrupt_in_urb); -+ - return status; - } - -@@ -931,7 +938,6 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port) - spin_unlock_irqrestore(&garmin_data_p->lock, flags); - - /* shutdown any bulk reads that might be going on */ -- usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - - if (garmin_data_p->state == STATE_RESET) -@@ -954,7 +960,7 @@ static void garmin_close(struct usb_serial_port *port) - - /* shutdown our urbs */ - usb_kill_urb(port->read_urb); -- usb_kill_urb(port->write_urb); -+ usb_kill_anchored_urbs(&garmin_data_p->write_urbs); - - /* keep reset state so we know that we must start a new session */ - if (garmin_data_p->state != STATE_RESET) -@@ -1038,12 +1044,14 @@ static int garmin_write_bulk(struct usb_serial_port *port, - } - - /* send it down the pipe */ -+ usb_anchor_urb(urb, &garmin_data_p->write_urbs); - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - dev_err(&port->dev, - "%s - usb_submit_urb(write bulk) failed with status = %d\n", - __func__, status); - count = status; -+ usb_unanchor_urb(urb); - kfree(buffer); - } - -@@ -1402,9 +1410,16 @@ static int garmin_port_probe(struct usb_serial_port *port) - garmin_data_p->state = 0; - garmin_data_p->flags = 0; - garmin_data_p->count = 0; -+ init_usb_anchor(&garmin_data_p->write_urbs); - usb_set_serial_port_data(port, garmin_data_p); - - status = garmin_init_session(port); -+ if (status) -+ goto err_free; -+ -+ return 0; -+err_free: -+ kfree(garmin_data_p); - - return status; - } -@@ -1414,6 +1429,7 @@ static int garmin_port_remove(struct usb_serial_port *port) - { - struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - -+ usb_kill_anchored_urbs(&garmin_data_p->write_urbs); - usb_kill_urb(port->interrupt_in_urb); - del_timer_sync(&garmin_data_p->timer); - kfree(garmin_data_p); -diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c -index e1c1e329c877..4516291df1b8 100644 ---- a/drivers/usb/serial/qcserial.c -+++ b/drivers/usb/serial/qcserial.c -@@ -148,6 +148,7 @@ static const struct usb_device_id id_table[] = { - {DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */ - {DEVICE_SWI(0x1199, 0x68c0)}, /* Sierra Wireless MC7304/MC7354 */ - {DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */ -+ {DEVICE_SWI(0x1199, 0x901e)}, /* Sierra Wireless EM7355 QDL */ - {DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */ - {DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */ - {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */ -diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c -index dd88ba1d71ce..35373e2065b2 100644 ---- a/drivers/video/backlight/adp5520_bl.c -+++ b/drivers/video/backlight/adp5520_bl.c -@@ -332,10 +332,18 @@ static int adp5520_bl_probe(struct platform_device *pdev) - } - - platform_set_drvdata(pdev, bl); -- ret |= adp5520_bl_setup(bl); -+ ret = adp5520_bl_setup(bl); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to setup\n"); -+ if (data->pdata->en_ambl_sens) -+ sysfs_remove_group(&bl->dev.kobj, -+ &adp5520_bl_attr_group); -+ return ret; -+ } -+ - backlight_update_status(bl); - -- return ret; -+ return 0; - } - - static int adp5520_bl_remove(struct platform_device *pdev) -diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c -index 7de847df224f..4b40c6a4d441 100644 ---- a/drivers/video/backlight/lcd.c -+++ b/drivers/video/backlight/lcd.c -@@ -226,6 +226,8 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, - dev_set_name(&new_ld->dev, "%s", name); - dev_set_drvdata(&new_ld->dev, devdata); - -+ new_ld->ops = ops; -+ - rc = device_register(&new_ld->dev); - if (rc) { - put_device(&new_ld->dev); -@@ -238,8 +240,6 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, - return ERR_PTR(rc); - } - -- new_ld->ops = ops; -- - return new_ld; - } - EXPORT_SYMBOL(lcd_device_register); -diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 194a6baa4283..4df1cb19a243 100644 ---- a/fs/ext4/inode.c -+++ b/fs/ext4/inode.c -@@ -658,6 +658,20 @@ has_zeroout: - ret = check_block_validity(inode, map); - if (ret != 0) - return ret; -+ -+ /* -+ * Inodes with freshly allocated blocks where contents will be -+ * visible after transaction commit must be on transaction's -+ * ordered data list. -+ */ -+ if (map->m_flags & EXT4_MAP_NEW && -+ !(map->m_flags & EXT4_MAP_UNWRITTEN) && -+ !IS_NOQUOTA(inode) && -+ ext4_should_order_data(inode)) { -+ ret = ext4_jbd2_file_inode(handle, inode); -+ if (ret) -+ return ret; -+ } - } - return retval; - } -@@ -1152,15 +1166,6 @@ static int ext4_write_end(struct file *file, - int i_size_changed = 0; - - trace_ext4_write_end(inode, pos, len, copied); -- if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) { -- ret = ext4_jbd2_file_inode(handle, inode); -- if (ret) { -- unlock_page(page); -- page_cache_release(page); -- goto errout; -- } -- } -- - if (ext4_has_inline_data(inode)) { - ret = ext4_write_inline_data_end(inode, pos, len, - copied, page); -diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h -index 4b4b056a6eb0..5148150cc80b 100644 ---- a/include/asm-generic/memory_model.h -+++ b/include/asm-generic/memory_model.h -@@ -1,6 +1,8 @@ - #ifndef __ASM_MEMORY_MODEL_H - #define __ASM_MEMORY_MODEL_H - -+#include -+ - #ifndef __ASSEMBLY__ - - #if defined(CONFIG_FLATMEM) -@@ -72,7 +74,7 @@ - /* - * Convert a physical address to a Page Frame Number and back - */ --#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) -+#define __phys_to_pfn(paddr) PHYS_PFN(paddr) - #define __pfn_to_phys(pfn) PFN_PHYS(pfn) - - #define page_to_pfn __page_to_pfn -diff --git a/include/dt-bindings/pinctrl/omap.h b/include/dt-bindings/pinctrl/omap.h -index 13949259705a..0d4fe32b3ae2 100644 ---- a/include/dt-bindings/pinctrl/omap.h -+++ b/include/dt-bindings/pinctrl/omap.h -@@ -45,8 +45,8 @@ - #define PIN_OFF_NONE 0 - #define PIN_OFF_OUTPUT_HIGH (OFF_EN | OFFOUT_EN | OFFOUT_VAL) - #define PIN_OFF_OUTPUT_LOW (OFF_EN | OFFOUT_EN) --#define PIN_OFF_INPUT_PULLUP (OFF_EN | OFF_PULL_EN | OFF_PULL_UP) --#define PIN_OFF_INPUT_PULLDOWN (OFF_EN | OFF_PULL_EN) -+#define PIN_OFF_INPUT_PULLUP (OFF_EN | OFFOUT_EN | OFF_PULL_EN | OFF_PULL_UP) -+#define PIN_OFF_INPUT_PULLDOWN (OFF_EN | OFFOUT_EN | OFF_PULL_EN) - #define PIN_OFF_WAKEUPENABLE WAKEUP_EN - - /* -diff --git a/include/linux/pfn.h b/include/linux/pfn.h -index 7646637221f3..97f3e88aead4 100644 ---- a/include/linux/pfn.h -+++ b/include/linux/pfn.h -@@ -9,5 +9,6 @@ - #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) - #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - #define PFN_PHYS(x) ((phys_addr_t)(x) << PAGE_SHIFT) -+#define PHYS_PFN(x) ((unsigned long)((x) >> PAGE_SHIFT)) - - #endif -diff --git a/include/uapi/linux/rds.h b/include/uapi/linux/rds.h -index 7af20a136429..804c9b2bfce3 100644 ---- a/include/uapi/linux/rds.h -+++ b/include/uapi/linux/rds.h -@@ -104,8 +104,8 @@ - #define RDS_INFO_LAST 10010 - - struct rds_info_counter { -- uint8_t name[32]; -- uint64_t value; -+ __u8 name[32]; -+ __u64 value; - } __attribute__((packed)); - - #define RDS_INFO_CONNECTION_FLAG_SENDING 0x01 -@@ -115,35 +115,35 @@ struct rds_info_counter { - #define TRANSNAMSIZ 16 - - struct rds_info_connection { -- uint64_t next_tx_seq; -- uint64_t next_rx_seq; -+ __u64 next_tx_seq; -+ __u64 next_rx_seq; - __be32 laddr; - __be32 faddr; -- uint8_t transport[TRANSNAMSIZ]; /* null term ascii */ -- uint8_t flags; -+ __u8 transport[TRANSNAMSIZ]; /* null term ascii */ -+ __u8 flags; - } __attribute__((packed)); - - #define RDS_INFO_MESSAGE_FLAG_ACK 0x01 - #define RDS_INFO_MESSAGE_FLAG_FAST_ACK 0x02 - - struct rds_info_message { -- uint64_t seq; -- uint32_t len; -+ __u64 seq; -+ __u32 len; - __be32 laddr; - __be32 faddr; - __be16 lport; - __be16 fport; -- uint8_t flags; -+ __u8 flags; - } __attribute__((packed)); - - struct rds_info_socket { -- uint32_t sndbuf; -+ __u32 sndbuf; - __be32 bound_addr; - __be32 connected_addr; - __be16 bound_port; - __be16 connected_port; -- uint32_t rcvbuf; -- uint64_t inum; -+ __u32 rcvbuf; -+ __u64 inum; - } __attribute__((packed)); - - struct rds_info_tcp_socket { -@@ -151,25 +151,25 @@ struct rds_info_tcp_socket { - __be16 local_port; - __be32 peer_addr; - __be16 peer_port; -- uint64_t hdr_rem; -- uint64_t data_rem; -- uint32_t last_sent_nxt; -- uint32_t last_expected_una; -- uint32_t last_seen_una; -+ __u64 hdr_rem; -+ __u64 data_rem; -+ __u32 last_sent_nxt; -+ __u32 last_expected_una; -+ __u32 last_seen_una; - } __attribute__((packed)); - - #define RDS_IB_GID_LEN 16 - struct rds_info_rdma_connection { - __be32 src_addr; - __be32 dst_addr; -- uint8_t src_gid[RDS_IB_GID_LEN]; -- uint8_t dst_gid[RDS_IB_GID_LEN]; -+ __u8 src_gid[RDS_IB_GID_LEN]; -+ __u8 dst_gid[RDS_IB_GID_LEN]; - -- uint32_t max_send_wr; -- uint32_t max_recv_wr; -- uint32_t max_send_sge; -- uint32_t rdma_mr_max; -- uint32_t rdma_mr_size; -+ __u32 max_send_wr; -+ __u32 max_recv_wr; -+ __u32 max_send_sge; -+ __u32 rdma_mr_max; -+ __u32 rdma_mr_size; - }; - - /* -@@ -210,70 +210,70 @@ struct rds_info_rdma_connection { - * (so that the application does not have to worry about - * alignment). - */ --typedef uint64_t rds_rdma_cookie_t; -+typedef __u64 rds_rdma_cookie_t; - - struct rds_iovec { -- uint64_t addr; -- uint64_t bytes; -+ __u64 addr; -+ __u64 bytes; - }; - - struct rds_get_mr_args { - struct rds_iovec vec; -- uint64_t cookie_addr; -- uint64_t flags; -+ __u64 cookie_addr; -+ __u64 flags; - }; - - struct rds_get_mr_for_dest_args { - struct __kernel_sockaddr_storage dest_addr; - struct rds_iovec vec; -- uint64_t cookie_addr; -- uint64_t flags; -+ __u64 cookie_addr; -+ __u64 flags; - }; - - struct rds_free_mr_args { - rds_rdma_cookie_t cookie; -- uint64_t flags; -+ __u64 flags; - }; - - struct rds_rdma_args { - rds_rdma_cookie_t cookie; - struct rds_iovec remote_vec; -- uint64_t local_vec_addr; -- uint64_t nr_local; -- uint64_t flags; -- uint64_t user_token; -+ __u64 local_vec_addr; -+ __u64 nr_local; -+ __u64 flags; -+ __u64 user_token; - }; - - struct rds_atomic_args { - rds_rdma_cookie_t cookie; -- uint64_t local_addr; -- uint64_t remote_addr; -+ __u64 local_addr; -+ __u64 remote_addr; - union { - struct { -- uint64_t compare; -- uint64_t swap; -+ __u64 compare; -+ __u64 swap; - } cswp; - struct { -- uint64_t add; -+ __u64 add; - } fadd; - struct { -- uint64_t compare; -- uint64_t swap; -- uint64_t compare_mask; -- uint64_t swap_mask; -+ __u64 compare; -+ __u64 swap; -+ __u64 compare_mask; -+ __u64 swap_mask; - } m_cswp; - struct { -- uint64_t add; -- uint64_t nocarry_mask; -+ __u64 add; -+ __u64 nocarry_mask; - } m_fadd; - }; -- uint64_t flags; -- uint64_t user_token; -+ __u64 flags; -+ __u64 user_token; - }; - - struct rds_rdma_notify { -- uint64_t user_token; -- int32_t status; -+ __u64 user_token; -+ __s32 status; - }; - - #define RDS_RDMA_SUCCESS 0 -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index 70dc6dcf8649..eb759f5008b8 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -313,7 +313,8 @@ static const char *const bpf_jmp_string[16] = { - [BPF_EXIT >> 4] = "exit", - }; - --static void print_bpf_insn(struct bpf_insn *insn) -+static void print_bpf_insn(const struct verifier_env *env, -+ const struct bpf_insn *insn) - { - u8 class = BPF_CLASS(insn->code); - -@@ -377,9 +378,19 @@ static void print_bpf_insn(struct bpf_insn *insn) - insn->code, - bpf_ldst_string[BPF_SIZE(insn->code) >> 3], - insn->src_reg, insn->imm); -- } else if (BPF_MODE(insn->code) == BPF_IMM) { -- verbose("(%02x) r%d = 0x%x\n", -- insn->code, insn->dst_reg, insn->imm); -+ } else if (BPF_MODE(insn->code) == BPF_IMM && -+ BPF_SIZE(insn->code) == BPF_DW) { -+ /* At this point, we already made sure that the second -+ * part of the ldimm64 insn is accessible. -+ */ -+ u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; -+ bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD; -+ -+ if (map_ptr && !env->allow_ptr_leaks) -+ imm = 0; -+ -+ verbose("(%02x) r%d = 0x%llx\n", insn->code, -+ insn->dst_reg, (unsigned long long)imm); - } else { - verbose("BUG_ld_%02x\n", insn->code); - return; -@@ -1764,7 +1775,7 @@ static int do_check(struct verifier_env *env) - - if (log_level) { - verbose("%d: ", insn_idx); -- print_bpf_insn(insn); -+ print_bpf_insn(env, insn); - } - - if (class == BPF_ALU || class == BPF_ALU64) { -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 73eec73ff733..7f0f689b8d2b 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -4453,6 +4453,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) - struct socket *sock; - int err = 0; - -+ /* Do not peel off from one netns to another one. */ -+ if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) -+ return -EINVAL; -+ - if (!asoc) - return -EINVAL; - -diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c -index 11467272089e..ea7b377f0378 100644 ---- a/sound/drivers/vx/vx_pcm.c -+++ b/sound/drivers/vx/vx_pcm.c -@@ -1015,7 +1015,7 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream - int size, space, count; - struct snd_pcm_runtime *runtime = subs->runtime; - -- if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) -+ if (!pipe->running || (chip->chip_status & VX_STAT_IS_STALE)) - return; - - size = runtime->buffer_size - snd_pcm_capture_avail(runtime); -@@ -1048,8 +1048,10 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream - /* ok, let's accelerate! */ - int align = pipe->align * 3; - space = (count / align) * align; -- vx_pseudo_dma_read(chip, runtime, pipe, space); -- count -= space; -+ if (space > 0) { -+ vx_pseudo_dma_read(chip, runtime, pipe, space); -+ count -= space; -+ } - } - /* read the rest of bytes */ - while (count > 0) { -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index a83688f8672e..af0962307b7f 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -338,6 +338,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) - case 0x10ec0288: - case 0x10ec0295: - case 0x10ec0298: -+ case 0x10ec0299: - alc_update_coef_idx(codec, 0x10, 1<<9, 0); - break; - case 0x10ec0285: -@@ -914,6 +915,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = { - { 0x10ec0256, 0x1028, 0, "ALC3246" }, - { 0x10ec0225, 0x1028, 0, "ALC3253" }, - { 0x10ec0295, 0x1028, 0, "ALC3254" }, -+ { 0x10ec0299, 0x1028, 0, "ALC3271" }, - { 0x10ec0670, 0x1025, 0, "ALC669X" }, - { 0x10ec0676, 0x1025, 0, "ALC679X" }, - { 0x10ec0282, 0x1043, 0, "ALC3229" }, -@@ -3721,6 +3723,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - break; - } -@@ -3823,6 +3826,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10); - snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); - alc_process_coef_fw(codec, coef0225); -@@ -3881,6 +3885,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) - switch (codec->core.vendor_id) { - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - break; - case 0x10ec0236: -@@ -3995,6 +4000,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - break; - } -@@ -4086,6 +4092,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - break; - } -@@ -4171,6 +4178,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - msleep(800); - val = alc_read_coef_idx(codec, 0x46); -@@ -6233,6 +6241,7 @@ static int patch_alc269(struct hda_codec *codec) - break; - case 0x10ec0225: - case 0x10ec0295: -+ case 0x10ec0299: - spec->codec_variant = ALC269_TYPE_ALC225; - break; - case 0x10ec0234: -@@ -7191,6 +7200,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { - HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269), - HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), -+ HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269), - HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), - HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd), - HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861), -diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c -index af83b3b38052..8e457ea27f89 100644 ---- a/sound/pci/vx222/vx222_ops.c -+++ b/sound/pci/vx222/vx222_ops.c -@@ -269,12 +269,12 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - - /* Transfer using pseudo-dma. - */ -- if (offset + count > pipe->buffer_bytes) { -+ if (offset + count >= pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ -- while (length-- > 0) { -+ for (; length > 0; length--) { - outl(cpu_to_le32(*addr), port); - addr++; - } -@@ -284,7 +284,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - pipe->hw_ptr += count; - count >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ -- while (count-- > 0) { -+ for (; count > 0; count--) { - outl(cpu_to_le32(*addr), port); - addr++; - } -@@ -307,12 +307,12 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - vx2_setup_pseudo_dma(chip, 0); - /* Transfer using pseudo-dma. - */ -- if (offset + count > pipe->buffer_bytes) { -+ if (offset + count >= pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ -- while (length-- > 0) -+ for (; length > 0; length--) - *addr++ = le32_to_cpu(inl(port)); - addr = (u32 *)runtime->dma_area; - pipe->hw_ptr = 0; -@@ -320,7 +320,7 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - pipe->hw_ptr += count; - count >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ -- while (count-- > 0) -+ for (; count > 0; count--) - *addr++ = le32_to_cpu(inl(port)); - - vx2_release_pseudo_dma(chip); -diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c -index 281972913c32..56aa1ba73ccc 100644 ---- a/sound/pcmcia/vx/vxp_ops.c -+++ b/sound/pcmcia/vx/vxp_ops.c -@@ -369,12 +369,12 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); - - vx_setup_pseudo_dma(chip, 1); -- if (offset + count > pipe->buffer_bytes) { -+ if (offset + count >= pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ -- while (length-- > 0) { -+ for (; length > 0; length--) { - outw(cpu_to_le16(*addr), port); - addr++; - } -@@ -384,7 +384,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - pipe->hw_ptr += count; - count >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ -- while (count-- > 0) { -+ for (; count > 0; count--) { - outw(cpu_to_le16(*addr), port); - addr++; - } -@@ -411,12 +411,12 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - if (snd_BUG_ON(count % 2)) - return; - vx_setup_pseudo_dma(chip, 0); -- if (offset + count > pipe->buffer_bytes) { -+ if (offset + count >= pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ -- while (length-- > 0) -+ for (; length > 0; length--) - *addr++ = le16_to_cpu(inw(port)); - addr = (unsigned short *)runtime->dma_area; - pipe->hw_ptr = 0; -@@ -424,7 +424,7 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - pipe->hw_ptr += count; - count >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ -- while (count-- > 1) -+ for (; count > 1; count--) - *addr++ = le16_to_cpu(inw(port)); - /* Disable DMA */ - pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK; diff --git a/patch/kernel/rockchip-default/stowed/04-patch-4.4.100-101.patch b/patch/kernel/rockchip-default/stowed/04-patch-4.4.100-101.patch deleted file mode 100644 index 2fa1df057..000000000 --- a/patch/kernel/rockchip-default/stowed/04-patch-4.4.100-101.patch +++ /dev/null @@ -1,718 +0,0 @@ -diff --git a/Makefile b/Makefile -index 91dd7832f499..0d7b050427ed 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 100 -+SUBLEVEL = 101 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c -index 210826d5bba5..9119722eb347 100644 ---- a/arch/arm64/kernel/traps.c -+++ b/arch/arm64/kernel/traps.c -@@ -64,8 +64,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - - /* - * We need to switch to kernel mode so that we can use __get_user -- * to safely read from kernel space. Note that we now dump the -- * code first, just in case the backtrace kills us. -+ * to safely read from kernel space. - */ - fs = get_fs(); - set_fs(KERNEL_DS); -@@ -111,21 +110,12 @@ static void dump_backtrace_entry(unsigned long where) - print_ip_sym(where); - } - --static void dump_instr(const char *lvl, struct pt_regs *regs) -+static void __dump_instr(const char *lvl, struct pt_regs *regs) - { - unsigned long addr = instruction_pointer(regs); -- mm_segment_t fs; - char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; - int i; - -- /* -- * We need to switch to kernel mode so that we can use __get_user -- * to safely read from kernel space. Note that we now dump the -- * code first, just in case the backtrace kills us. -- */ -- fs = get_fs(); -- set_fs(KERNEL_DS); -- - for (i = -4; i < 1; i++) { - unsigned int val, bad; - -@@ -139,8 +129,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) - } - } - printk("%sCode: %s\n", lvl, str); -+} - -- set_fs(fs); -+static void dump_instr(const char *lvl, struct pt_regs *regs) -+{ -+ if (!user_mode(regs)) { -+ mm_segment_t fs = get_fs(); -+ set_fs(KERNEL_DS); -+ __dump_instr(lvl, regs); -+ set_fs(fs); -+ } else { -+ __dump_instr(lvl, regs); -+ } - } - - static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) -diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c -index 25372dc381d4..5cb5e8ff0224 100644 ---- a/drivers/char/ipmi/ipmi_msghandler.c -+++ b/drivers/char/ipmi/ipmi_msghandler.c -@@ -4029,7 +4029,8 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, - } - - static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, -- struct list_head *timeouts, long timeout_period, -+ struct list_head *timeouts, -+ unsigned long timeout_period, - int slot, unsigned long *flags, - unsigned int *waiting_msgs) - { -@@ -4042,8 +4043,8 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, - if (!ent->inuse) - return; - -- ent->timeout -= timeout_period; -- if (ent->timeout > 0) { -+ if (timeout_period < ent->timeout) { -+ ent->timeout -= timeout_period; - (*waiting_msgs)++; - return; - } -@@ -4109,7 +4110,8 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, - } - } - --static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, long timeout_period) -+static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, -+ unsigned long timeout_period) - { - struct list_head timeouts; - struct ipmi_recv_msg *msg, *msg2; -diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c -index 5dca77e0ffed..2cb34b0f3856 100644 ---- a/drivers/net/bonding/bond_main.c -+++ b/drivers/net/bonding/bond_main.c -@@ -3166,7 +3166,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) - hash ^= (hash >> 16); - hash ^= (hash >> 8); - -- return hash; -+ return hash >> 1; - } - - /*-------------------------- Device entry points ----------------------------*/ -diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c -index b1b9ebafb354..a3b2e23921bf 100644 ---- a/drivers/net/ethernet/fealnx.c -+++ b/drivers/net/ethernet/fealnx.c -@@ -257,8 +257,8 @@ enum rx_desc_status_bits { - RXFSD = 0x00000800, /* first descriptor */ - RXLSD = 0x00000400, /* last descriptor */ - ErrorSummary = 0x80, /* error summary */ -- RUNT = 0x40, /* runt packet received */ -- LONG = 0x20, /* long packet received */ -+ RUNTPKT = 0x40, /* runt packet received */ -+ LONGPKT = 0x20, /* long packet received */ - FAE = 0x10, /* frame align error */ - CRC = 0x08, /* crc error */ - RXER = 0x04, /* receive error */ -@@ -1633,7 +1633,7 @@ static int netdev_rx(struct net_device *dev) - dev->name, rx_status); - - dev->stats.rx_errors++; /* end of a packet. */ -- if (rx_status & (LONG | RUNT)) -+ if (rx_status & (LONGPKT | RUNTPKT)) - dev->stats.rx_length_errors++; - if (rx_status & RXER) - dev->stats.rx_frame_errors++; -diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c -index 669edbd47602..d6ceb8b91cd6 100644 ---- a/drivers/nvme/host/pci.c -+++ b/drivers/nvme/host/pci.c -@@ -350,8 +350,8 @@ static void async_completion(struct nvme_queue *nvmeq, void *ctx, - struct async_cmd_info *cmdinfo = ctx; - cmdinfo->result = le32_to_cpup(&cqe->result); - cmdinfo->status = le16_to_cpup(&cqe->status) >> 1; -- queue_kthread_work(cmdinfo->worker, &cmdinfo->work); - blk_mq_free_request(cmdinfo->req); -+ queue_kthread_work(cmdinfo->worker, &cmdinfo->work); - } - - static inline struct nvme_cmd_info *get_cmd_from_tag(struct nvme_queue *nvmeq, -diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c -index de1c143b475f..21fc9b3a27cf 100644 ---- a/drivers/tty/serial/omap-serial.c -+++ b/drivers/tty/serial/omap-serial.c -@@ -693,7 +693,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) - if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS)) - up->efr |= UART_EFR_RTS; - else -- up->efr &= UART_EFR_RTS; -+ up->efr &= ~UART_EFR_RTS; - serial_out(up, UART_EFR, up->efr); - serial_out(up, UART_LCR, lcr); - -diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c -index f6c6c8adbc01..7289f0a7670b 100644 ---- a/fs/coda/upcall.c -+++ b/fs/coda/upcall.c -@@ -446,8 +446,7 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid) - UPARG(CODA_FSYNC); - - inp->coda_fsync.VFid = *fid; -- error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs), -- &outsize, inp); -+ error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); - - CODA_FREE(inp, insize); - return error; -diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c -index 1d738723a41a..501ecc4a1ac4 100644 ---- a/fs/ocfs2/file.c -+++ b/fs/ocfs2/file.c -@@ -1166,6 +1166,13 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) - } - size_change = S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE; - if (size_change) { -+ /* -+ * Here we should wait dio to finish before inode lock -+ * to avoid a deadlock between ocfs2_setattr() and -+ * ocfs2_dio_end_io_write() -+ */ -+ inode_dio_wait(inode); -+ - status = ocfs2_rw_lock(inode, 1); - if (status < 0) { - mlog_errno(status); -@@ -1186,8 +1193,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) - if (status) - goto bail_unlock; - -- inode_dio_wait(inode); -- - if (i_size_read(inode) >= attr->ia_size) { - if (ocfs2_should_order_data(inode)) { - status = ocfs2_begin_ordered_truncate(inode, -diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h -index 5b609a3ce3d7..ff88d6189411 100644 ---- a/include/linux/mmzone.h -+++ b/include/linux/mmzone.h -@@ -688,7 +688,8 @@ typedef struct pglist_data { - * is the first PFN that needs to be initialised. - */ - unsigned long first_deferred_pfn; -- unsigned long static_init_size; -+ /* Number of non-deferred pages */ -+ unsigned long static_init_pgcnt; - #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ - } pg_data_t; - -diff --git a/include/linux/page_idle.h b/include/linux/page_idle.h -index bf268fa92c5b..fec40271339f 100644 ---- a/include/linux/page_idle.h -+++ b/include/linux/page_idle.h -@@ -46,33 +46,62 @@ extern struct page_ext_operations page_idle_ops; - - static inline bool page_is_young(struct page *page) - { -- return test_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return false; -+ -+ return test_bit(PAGE_EXT_YOUNG, &page_ext->flags); - } - - static inline void set_page_young(struct page *page) - { -- set_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return; -+ -+ set_bit(PAGE_EXT_YOUNG, &page_ext->flags); - } - - static inline bool test_and_clear_page_young(struct page *page) - { -- return test_and_clear_bit(PAGE_EXT_YOUNG, -- &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return false; -+ -+ return test_and_clear_bit(PAGE_EXT_YOUNG, &page_ext->flags); - } - - static inline bool page_is_idle(struct page *page) - { -- return test_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return false; -+ -+ return test_bit(PAGE_EXT_IDLE, &page_ext->flags); - } - - static inline void set_page_idle(struct page *page) - { -- set_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return; -+ -+ set_bit(PAGE_EXT_IDLE, &page_ext->flags); - } - - static inline void clear_page_idle(struct page *page) - { -- clear_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags); -+ struct page_ext *page_ext = lookup_page_ext(page); -+ -+ if (unlikely(!page_ext)) -+ return; -+ -+ clear_bit(PAGE_EXT_IDLE, &page_ext->flags); - } - #endif /* CONFIG_64BIT */ - -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index 3f61c647fc5c..b5421f6f155a 100644 ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -3400,6 +3400,13 @@ static inline void nf_reset_trace(struct sk_buff *skb) - #endif - } - -+static inline void ipvs_reset(struct sk_buff *skb) -+{ -+#if IS_ENABLED(CONFIG_IP_VS) -+ skb->ipvs_property = 0; -+#endif -+} -+ - /* Note: This doesn't put any conntrack and bridge info in dst. */ - static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src, - bool copy) -diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c -index 5bf5906ce13b..fe1c61f7cf26 100644 ---- a/mm/debug-pagealloc.c -+++ b/mm/debug-pagealloc.c -@@ -34,6 +34,8 @@ static inline void set_page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -+ if (page_ext) -+ return; - __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } - -@@ -42,6 +44,8 @@ static inline void clear_page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -+ if (page_ext) -+ return; - __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } - -@@ -50,6 +54,8 @@ static inline bool page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -+ if (page_ext) -+ return false; - return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } - -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 6b5421ae86c6..3c70f03d91ec 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -267,28 +267,37 @@ EXPORT_SYMBOL(nr_online_nodes); - int page_group_by_mobility_disabled __read_mostly; - - #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT -+ -+/* -+ * Determine how many pages need to be initialized durig early boot -+ * (non-deferred initialization). -+ * The value of first_deferred_pfn will be set later, once non-deferred pages -+ * are initialized, but for now set it ULONG_MAX. -+ */ - static inline void reset_deferred_meminit(pg_data_t *pgdat) - { -- unsigned long max_initialise; -- unsigned long reserved_lowmem; -+ phys_addr_t start_addr, end_addr; -+ unsigned long max_pgcnt; -+ unsigned long reserved; - - /* - * Initialise at least 2G of a node but also take into account that - * two large system hashes that can take up 1GB for 0.25TB/node. - */ -- max_initialise = max(2UL << (30 - PAGE_SHIFT), -- (pgdat->node_spanned_pages >> 8)); -+ max_pgcnt = max(2UL << (30 - PAGE_SHIFT), -+ (pgdat->node_spanned_pages >> 8)); - - /* - * Compensate the all the memblock reservations (e.g. crash kernel) - * from the initial estimation to make sure we will initialize enough - * memory to boot. - */ -- reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn, -- pgdat->node_start_pfn + max_initialise); -- max_initialise += reserved_lowmem; -+ start_addr = PFN_PHYS(pgdat->node_start_pfn); -+ end_addr = PFN_PHYS(pgdat->node_start_pfn + max_pgcnt); -+ reserved = memblock_reserved_memory_within(start_addr, end_addr); -+ max_pgcnt += PHYS_PFN(reserved); - -- pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages); -+ pgdat->static_init_pgcnt = min(max_pgcnt, pgdat->node_spanned_pages); - pgdat->first_deferred_pfn = ULONG_MAX; - } - -@@ -324,7 +333,7 @@ static inline bool update_defer_init(pg_data_t *pgdat, - return true; - /* Initialise at least 2G of the highest zone */ - (*nr_initialised)++; -- if ((*nr_initialised > pgdat->static_init_size) && -+ if ((*nr_initialised > pgdat->static_init_pgcnt) && - (pfn & (PAGES_PER_SECTION - 1)) == 0) { - pgdat->first_deferred_pfn = pfn; - return false; -@@ -560,6 +569,9 @@ static inline void set_page_guard(struct zone *zone, struct page *page, - return; - - page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ return; -+ - __set_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); - - INIT_LIST_HEAD(&page->lru); -@@ -577,6 +589,9 @@ static inline void clear_page_guard(struct zone *zone, struct page *page, - return; - - page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ return; -+ - __clear_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); - - set_page_private(page, 0); -diff --git a/mm/page_ext.c b/mm/page_ext.c -index 292ca7b8debd..4d1eac0d4fc5 100644 ---- a/mm/page_ext.c -+++ b/mm/page_ext.c -@@ -106,7 +106,6 @@ struct page_ext *lookup_page_ext(struct page *page) - struct page_ext *base; - - base = NODE_DATA(page_to_nid(page))->node_page_ext; --#ifdef CONFIG_DEBUG_VM - /* - * The sanity checks the page allocator does upon freeing a - * page can reach here before the page_ext arrays are -@@ -115,7 +114,6 @@ struct page_ext *lookup_page_ext(struct page *page) - */ - if (unlikely(!base)) - return NULL; --#endif - offset = pfn - round_down(node_start_pfn(page_to_nid(page)), - MAX_ORDER_NR_PAGES); - return base + offset; -@@ -180,7 +178,6 @@ struct page_ext *lookup_page_ext(struct page *page) - { - unsigned long pfn = page_to_pfn(page); - struct mem_section *section = __pfn_to_section(pfn); --#ifdef CONFIG_DEBUG_VM - /* - * The sanity checks the page allocator does upon freeing a - * page can reach here before the page_ext arrays are -@@ -189,7 +186,6 @@ struct page_ext *lookup_page_ext(struct page *page) - */ - if (!section->page_ext) - return NULL; --#endif - return section->page_ext + pfn; - } - -diff --git a/mm/page_owner.c b/mm/page_owner.c -index 983c3a10fa07..dd6b9cebf981 100644 ---- a/mm/page_owner.c -+++ b/mm/page_owner.c -@@ -53,6 +53,8 @@ void __reset_page_owner(struct page *page, unsigned int order) - - for (i = 0; i < (1 << order); i++) { - page_ext = lookup_page_ext(page + i); -+ if (unlikely(!page_ext)) -+ continue; - __clear_bit(PAGE_EXT_OWNER, &page_ext->flags); - } - } -@@ -60,6 +62,7 @@ void __reset_page_owner(struct page *page, unsigned int order) - void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask) - { - struct page_ext *page_ext = lookup_page_ext(page); -+ - struct stack_trace trace = { - .nr_entries = 0, - .max_entries = ARRAY_SIZE(page_ext->trace_entries), -@@ -67,6 +70,9 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask) - .skip = 3, - }; - -+ if (unlikely(!page_ext)) -+ return; -+ - save_stack_trace(&trace); - - page_ext->order = order; -@@ -79,6 +85,12 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask) - gfp_t __get_page_owner_gfp(struct page *page) - { - struct page_ext *page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ /* -+ * The caller just returns 0 if no valid gfp -+ * So return 0 here too. -+ */ -+ return 0; - - return page_ext->gfp_mask; - } -@@ -194,6 +206,8 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) - } - - page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ continue; - - /* - * Some pages could be missed by concurrent allocation or free, -@@ -257,6 +271,8 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone) - continue; - - page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ continue; - - /* Maybe overraping zone */ - if (test_bit(PAGE_EXT_OWNER, &page_ext->flags)) -diff --git a/mm/pagewalk.c b/mm/pagewalk.c -index 29f2f8b853ae..c2cbd2620169 100644 ---- a/mm/pagewalk.c -+++ b/mm/pagewalk.c -@@ -142,8 +142,12 @@ static int walk_hugetlb_range(unsigned long addr, unsigned long end, - do { - next = hugetlb_entry_end(h, addr, end); - pte = huge_pte_offset(walk->mm, addr & hmask); -- if (pte && walk->hugetlb_entry) -+ -+ if (pte) - err = walk->hugetlb_entry(pte, hmask, addr, next, walk); -+ else if (walk->pte_hole) -+ err = walk->pte_hole(addr, next, walk); -+ - if (err) - break; - } while (addr = next, addr != end); -diff --git a/mm/vmstat.c b/mm/vmstat.c -index c54fd2924f25..c344e3609c53 100644 ---- a/mm/vmstat.c -+++ b/mm/vmstat.c -@@ -1091,6 +1091,8 @@ static void pagetypeinfo_showmixedcount_print(struct seq_file *m, - continue; - - page_ext = lookup_page_ext(page); -+ if (unlikely(!page_ext)) -+ continue; - - if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) - continue; -diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c -index 5e4199d5a388..01abb6431fd9 100644 ---- a/net/8021q/vlan.c -+++ b/net/8021q/vlan.c -@@ -376,6 +376,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, - dev->name); - vlan_vid_add(dev, htons(ETH_P_8021Q), 0); - } -+ if (event == NETDEV_DOWN && -+ (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) -+ vlan_vid_del(dev, htons(ETH_P_8021Q), 0); - - vlan_info = rtnl_dereference(dev->vlan_info); - if (!vlan_info) -@@ -423,9 +426,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, - struct net_device *tmp; - LIST_HEAD(close_list); - -- if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) -- vlan_vid_del(dev, htons(ETH_P_8021Q), 0); -- - /* Put all VLANs for this dev in the down state too. */ - vlan_group_for_each_dev(grp, i, vlandev) { - flgs = vlandev->flags; -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index 73dfd7729bc9..d33609c2f276 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -4229,6 +4229,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) - if (!xnet) - return; - -+ ipvs_reset(skb); - skb_orphan(skb); - skb->mark = 0; - } -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index 64c7ce847584..39c2919fe0d3 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -3018,13 +3018,8 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, - tcp_ecn_make_synack(req, th); - th->source = htons(ireq->ir_num); - th->dest = ireq->ir_rmt_port; -- /* Setting of flags are superfluous here for callers (and ECE is -- * not even correctly set) -- */ -- tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, -- TCPHDR_SYN | TCPHDR_ACK); -- -- th->seq = htonl(TCP_SKB_CB(skb)->seq); -+ skb->ip_summed = CHECKSUM_PARTIAL; -+ th->seq = htonl(tcp_rsk(req)->snt_isn); - /* XXX data is queued and acked as is. No buffer/window check */ - th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); - -diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c -index acfb16fdcd55..9ecdd61c6463 100644 ---- a/net/netlink/af_netlink.c -+++ b/net/netlink/af_netlink.c -@@ -2077,7 +2077,7 @@ static int netlink_dump(struct sock *sk) - struct sk_buff *skb = NULL; - struct nlmsghdr *nlh; - struct module *module; -- int len, err = -ENOBUFS; -+ int err = -ENOBUFS; - int alloc_min_size; - int alloc_size; - -@@ -2125,9 +2125,11 @@ static int netlink_dump(struct sock *sk) - skb_reserve(skb, skb_tailroom(skb) - alloc_size); - netlink_skb_set_owner_r(skb, sk); - -- len = cb->dump(skb, cb); -+ if (nlk->dump_done_errno > 0) -+ nlk->dump_done_errno = cb->dump(skb, cb); - -- if (len > 0) { -+ if (nlk->dump_done_errno > 0 || -+ skb_tailroom(skb) < nlmsg_total_size(sizeof(nlk->dump_done_errno))) { - mutex_unlock(nlk->cb_mutex); - - if (sk_filter(sk, skb)) -@@ -2137,13 +2139,15 @@ static int netlink_dump(struct sock *sk) - return 0; - } - -- nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); -- if (!nlh) -+ nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, -+ sizeof(nlk->dump_done_errno), NLM_F_MULTI); -+ if (WARN_ON(!nlh)) - goto errout_skb; - - nl_dump_check_consistent(cb, nlh); - -- memcpy(nlmsg_data(nlh), &len, sizeof(len)); -+ memcpy(nlmsg_data(nlh), &nlk->dump_done_errno, -+ sizeof(nlk->dump_done_errno)); - - if (sk_filter(sk, skb)) - kfree_skb(skb); -@@ -2208,6 +2212,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - cb->skb = skb; - - nlk->cb_running = true; -+ nlk->dump_done_errno = INT_MAX; - - mutex_unlock(nlk->cb_mutex); - -diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h -index ea4600aea6b0..d987696c0eb4 100644 ---- a/net/netlink/af_netlink.h -+++ b/net/netlink/af_netlink.h -@@ -38,6 +38,7 @@ struct netlink_sock { - wait_queue_head_t wait; - bool bound; - bool cb_running; -+ int dump_done_errno; - struct netlink_callback cb; - struct mutex *cb_mutex; - struct mutex cb_def_mutex; -diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c -index e33e9bd4ed5a..8a61ccc37e12 100644 ---- a/net/sctp/ipv6.c -+++ b/net/sctp/ipv6.c -@@ -806,6 +806,8 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, - if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) { - struct sctp_ulpevent *ev = sctp_skb2event(skb); - addr->v6.sin6_scope_id = ev->iif; -+ } else { -+ addr->v6.sin6_scope_id = 0; - } - } - -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 7f0f689b8d2b..272edd7748a0 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -4453,6 +4453,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) - struct socket *sock; - int err = 0; - -+ /* Do not peel off from one netns to another one. */ -+ if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) -+ return -EINVAL; -+ - /* Do not peel off from one netns to another one. */ - if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) - return -EINVAL; -diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c -index 9ce9d5003dcc..19014293f927 100644 ---- a/security/integrity/ima/ima_appraise.c -+++ b/security/integrity/ima/ima_appraise.c -@@ -297,6 +297,9 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) - if (iint->flags & IMA_DIGSIG) - return; - -+ if (iint->ima_file_status != INTEGRITY_PASS) -+ return; -+ - rc = ima_collect_measurement(iint, file, NULL, NULL); - if (rc < 0) - return; diff --git a/patch/kernel/rockchip-default/stowed/04-patch-4.4.101-102.patch b/patch/kernel/rockchip-default/stowed/04-patch-4.4.101-102.patch deleted file mode 100644 index 45e56d171..000000000 --- a/patch/kernel/rockchip-default/stowed/04-patch-4.4.101-102.patch +++ /dev/null @@ -1,43 +0,0 @@ -diff --git a/Makefile b/Makefile -index 0d7b050427ed..9e036fac9c04 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 101 -+SUBLEVEL = 102 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c -index fe1c61f7cf26..3b8f1b83610e 100644 ---- a/mm/debug-pagealloc.c -+++ b/mm/debug-pagealloc.c -@@ -34,7 +34,7 @@ static inline void set_page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -- if (page_ext) -+ if (!page_ext) - return; - __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } -@@ -44,7 +44,7 @@ static inline void clear_page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -- if (page_ext) -+ if (!page_ext) - return; - __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } -@@ -54,7 +54,7 @@ static inline bool page_poison(struct page *page) - struct page_ext *page_ext; - - page_ext = lookup_page_ext(page); -- if (page_ext) -+ if (!page_ext) - return false; - return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags); - } diff --git a/patch/kernel/rockchip-default/stowed/04-patch-4.4.102-103.patch b/patch/kernel/rockchip-default/stowed/04-patch-4.4.102-103.patch deleted file mode 100644 index e5cccc0c7..000000000 --- a/patch/kernel/rockchip-default/stowed/04-patch-4.4.102-103.patch +++ /dev/null @@ -1,3014 +0,0 @@ -diff --git a/Makefile b/Makefile -index 9e036fac9c04..f5a51cd7ca49 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - VERSION = 4 - PATCHLEVEL = 4 --SUBLEVEL = 102 -+SUBLEVEL = 103 - EXTRAVERSION = - NAME = Blurry Fish Butt - -diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c -index 9fe8e241335c..e1f6f0daa847 100644 ---- a/arch/arm/mm/dump.c -+++ b/arch/arm/mm/dump.c -@@ -126,8 +126,8 @@ static const struct prot_bits section_bits[] = { - .val = PMD_SECT_USER, - .set = "USR", - }, { -- .mask = L_PMD_SECT_RDONLY, -- .val = L_PMD_SECT_RDONLY, -+ .mask = L_PMD_SECT_RDONLY | PMD_SECT_AP2, -+ .val = L_PMD_SECT_RDONLY | PMD_SECT_AP2, - .set = "ro", - .clear = "RW", - #elif __LINUX_ARM_ARCH__ >= 6 -diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c -index 7f8cd1b3557f..c29ad610311b 100644 ---- a/arch/arm/mm/init.c -+++ b/arch/arm/mm/init.c -@@ -611,8 +611,8 @@ static struct section_perm ro_perms[] = { - .start = (unsigned long)_stext, - .end = (unsigned long)__init_begin, - #ifdef CONFIG_ARM_LPAE -- .mask = ~L_PMD_SECT_RDONLY, -- .prot = L_PMD_SECT_RDONLY, -+ .mask = ~(L_PMD_SECT_RDONLY | PMD_SECT_AP2), -+ .prot = L_PMD_SECT_RDONLY | PMD_SECT_AP2, - #else - .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), - .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, -diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c -index d20ae63eb3c2..46abe9e4e0e0 100644 ---- a/arch/mips/bcm47xx/leds.c -+++ b/arch/mips/bcm47xx/leds.c -@@ -330,7 +330,7 @@ bcm47xx_leds_linksys_wrt54g3gv2[] __initconst = { - /* Verified on: WRT54GS V1.0 */ - static const struct gpio_led - bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = { -- BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), -+ BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), - BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON), - BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF), - }; -diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c -index 24c115a0721a..a3f38e6b7ea1 100644 ---- a/arch/mips/kernel/ptrace.c -+++ b/arch/mips/kernel/ptrace.c -@@ -650,6 +650,19 @@ static const struct user_regset_view user_mips64_view = { - .n = ARRAY_SIZE(mips64_regsets), - }; - -+#ifdef CONFIG_MIPS32_N32 -+ -+static const struct user_regset_view user_mipsn32_view = { -+ .name = "mipsn32", -+ .e_flags = EF_MIPS_ABI2, -+ .e_machine = ELF_ARCH, -+ .ei_osabi = ELF_OSABI, -+ .regsets = mips64_regsets, -+ .n = ARRAY_SIZE(mips64_regsets), -+}; -+ -+#endif /* CONFIG_MIPS32_N32 */ -+ - #endif /* CONFIG_64BIT */ - - const struct user_regset_view *task_user_regset_view(struct task_struct *task) -@@ -660,6 +673,10 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) - #ifdef CONFIG_MIPS32_O32 - if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) - return &user_mips_view; -+#endif -+#ifdef CONFIG_MIPS32_N32 -+ if (test_tsk_thread_flag(task, TIF_32BIT_ADDR)) -+ return &user_mipsn32_view; - #endif - return &user_mips64_view; - #endif -diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c -index 48d6349fd9d7..c5f45fc96c74 100644 ---- a/arch/mips/ralink/mt7620.c -+++ b/arch/mips/ralink/mt7620.c -@@ -141,8 +141,8 @@ static struct rt2880_pmx_func i2c_grp_mt7628[] = { - FUNC("i2c", 0, 4, 2), - }; - --static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) }; --static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) }; -+static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("refclk", 0, 37, 1) }; -+static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 36, 1) }; - static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) }; - static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; - -diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S -index c6b855f7892c..9f22195b90ed 100644 ---- a/arch/parisc/kernel/syscall.S -+++ b/arch/parisc/kernel/syscall.S -@@ -688,15 +688,15 @@ cas_action: - /* ELF32 Process entry path */ - lws_compare_and_swap_2: - #ifdef CONFIG_64BIT -- /* Clip the input registers */ -+ /* Clip the input registers. We don't need to clip %r23 as we -+ only use it for word operations */ - depdi 0, 31, 32, %r26 - depdi 0, 31, 32, %r25 - depdi 0, 31, 32, %r24 -- depdi 0, 31, 32, %r23 - #endif - - /* Check the validity of the size pointer */ -- subi,>>= 4, %r23, %r0 -+ subi,>>= 3, %r23, %r0 - b,n lws_exit_nosys - - /* Jump to the functions which will load the old and new values into -diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c -index cf8c7e4e0b21..984a54c85952 100644 ---- a/arch/powerpc/kernel/signal.c -+++ b/arch/powerpc/kernel/signal.c -@@ -102,7 +102,7 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, - static void do_signal(struct pt_regs *regs) - { - sigset_t *oldset = sigmask_to_save(); -- struct ksignal ksig; -+ struct ksignal ksig = { .sig = 0 }; - int ret; - int is32 = is_32bit_task(); - -diff --git a/arch/s390/include/asm/asm-prototypes.h b/arch/s390/include/asm/asm-prototypes.h -new file mode 100644 -index 000000000000..2c3413b0ca52 ---- /dev/null -+++ b/arch/s390/include/asm/asm-prototypes.h -@@ -0,0 +1,8 @@ -+#ifndef _ASM_S390_PROTOTYPES_H -+ -+#include -+#include -+#include -+#include -+ -+#endif /* _ASM_S390_PROTOTYPES_H */ -diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h -index 12d45f0cfdd9..dde6b52359c5 100644 ---- a/arch/s390/include/asm/switch_to.h -+++ b/arch/s390/include/asm/switch_to.h -@@ -34,8 +34,8 @@ static inline void restore_access_regs(unsigned int *acrs) - save_access_regs(&prev->thread.acrs[0]); \ - save_ri_cb(prev->thread.ri_cb); \ - } \ -+ update_cr_regs(next); \ - if (next->mm) { \ -- update_cr_regs(next); \ - set_cpu_flag(CIF_FPU); \ - restore_access_regs(&next->thread.acrs[0]); \ - restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ -diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c -index 6e72961608f0..07477ba392b7 100644 ---- a/arch/s390/kernel/dis.c -+++ b/arch/s390/kernel/dis.c -@@ -1549,6 +1549,7 @@ static struct s390_insn opcode_e7[] = { - { "vfsq", 0xce, INSTR_VRR_VV000MM }, - { "vfs", 0xe2, INSTR_VRR_VVV00MM }, - { "vftci", 0x4a, INSTR_VRI_VVIMM }, -+ { "", 0, INSTR_INVALID } - }; - - static struct s390_insn opcode_eb[] = { -@@ -1961,7 +1962,7 @@ void show_code(struct pt_regs *regs) - { - char *mode = user_mode(regs) ? "User" : "Krnl"; - unsigned char code[64]; -- char buffer[64], *ptr; -+ char buffer[128], *ptr; - mm_segment_t old_fs; - unsigned long addr; - int start, end, opsize, hops, i; -@@ -2024,7 +2025,7 @@ void show_code(struct pt_regs *regs) - start += opsize; - printk(buffer); - ptr = buffer; -- ptr += sprintf(ptr, "\n "); -+ ptr += sprintf(ptr, "\n\t "); - hops++; - } - printk("\n"); -diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c -index 3c31609df959..ee7b8e7ca4f8 100644 ---- a/arch/s390/kernel/early.c -+++ b/arch/s390/kernel/early.c -@@ -325,8 +325,10 @@ static __init void detect_machine_facilities(void) - S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; - if (test_facility(40)) - S390_lowcore.machine_flags |= MACHINE_FLAG_LPP; -- if (test_facility(50) && test_facility(73)) -+ if (test_facility(50) && test_facility(73)) { - S390_lowcore.machine_flags |= MACHINE_FLAG_TE; -+ __ctl_set_bit(0, 55); -+ } - if (test_facility(51)) - S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; - if (test_facility(129)) { -diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c -index 114ee8b96f17..efa035a31b98 100644 ---- a/arch/s390/kernel/process.c -+++ b/arch/s390/kernel/process.c -@@ -137,6 +137,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, - memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); - memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); - clear_tsk_thread_flag(p, TIF_SINGLE_STEP); -+ p->thread.per_flags = 0; - /* Initialize per thread user and system timer values */ - ti = task_thread_info(p); - ti->user_timer = 0; -diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c -index fffa0e5462af..70cdb03d4acd 100644 ---- a/arch/s390/kernel/runtime_instr.c -+++ b/arch/s390/kernel/runtime_instr.c -@@ -47,11 +47,13 @@ void exit_thread_runtime_instr(void) - { - struct task_struct *task = current; - -+ preempt_disable(); - if (!task->thread.ri_cb) - return; - disable_runtime_instr(); - kfree(task->thread.ri_cb); - task->thread.ri_cb = NULL; -+ preempt_enable(); - } - - SYSCALL_DEFINE1(s390_runtime_instr, int, command) -@@ -62,9 +64,7 @@ SYSCALL_DEFINE1(s390_runtime_instr, int, command) - return -EOPNOTSUPP; - - if (command == S390_RUNTIME_INSTR_STOP) { -- preempt_disable(); - exit_thread_runtime_instr(); -- preempt_enable(); - return 0; - } - -diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c -index 899c40f826dd..4e1b254c3695 100644 ---- a/arch/x86/kvm/svm.c -+++ b/arch/x86/kvm/svm.c -@@ -3114,6 +3114,13 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) - u32 ecx = msr->index; - u64 data = msr->data; - switch (ecx) { -+ case MSR_IA32_CR_PAT: -+ if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data)) -+ return 1; -+ vcpu->arch.pat = data; -+ svm->vmcb->save.g_pat = data; -+ mark_dirty(svm->vmcb, VMCB_NPT); -+ break; - case MSR_IA32_TSC: - kvm_write_tsc(vcpu, msr); - break; -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index 9114588e3e61..67ba0d8f87c7 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -10394,6 +10394,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, - vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip); - vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base); - vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base); -+ vmcs_write32(GUEST_IDTR_LIMIT, 0xFFFF); -+ vmcs_write32(GUEST_GDTR_LIMIT, 0xFFFF); - - /* If not VM_EXIT_CLEAR_BNDCFGS, the L2 value propagates to L1. */ - if (vmcs12->vm_exit_controls & VM_EXIT_CLEAR_BNDCFGS) -diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt -index d388de72eaca..ec039f2a0c13 100644 ---- a/arch/x86/lib/x86-opcode-map.txt -+++ b/arch/x86/lib/x86-opcode-map.txt -@@ -833,7 +833,7 @@ EndTable - - GrpTable: Grp3_1 - 0: TEST Eb,Ib --1: -+1: TEST Eb,Ib - 2: NOT Eb - 3: NEG Eb - 4: MUL AL,Eb -diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c -index 91a9e6af2ec4..75cced210b2a 100644 ---- a/drivers/ata/libata-eh.c -+++ b/drivers/ata/libata-eh.c -@@ -2245,8 +2245,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) - if (dev->flags & ATA_DFLAG_DUBIOUS_XFER) - eflags |= ATA_EFLAG_DUBIOUS_XFER; - ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask); -+ trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask); - } -- trace_ata_eh_link_autopsy(dev, ehc->i.action, all_err_mask); - DPRINTK("EXIT\n"); - } - -diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c -index f8580900c273..db6e7e57081c 100644 ---- a/drivers/base/power/opp/core.c -+++ b/drivers/base/power/opp/core.c -@@ -1205,6 +1205,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np) - if (ret) { - dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, - ret); -+ of_node_put(np); - goto free_table; - } - } -diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c -index 2e14dfb588f4..7d060ffe8975 100644 ---- a/drivers/clk/ti/clk-dra7-atl.c -+++ b/drivers/clk/ti/clk-dra7-atl.c -@@ -265,7 +265,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) - - /* Get configuration for the ATL instances */ - snprintf(prop, sizeof(prop), "atl%u", i); -- cfg_node = of_find_node_by_name(node, prop); -+ cfg_node = of_get_child_by_name(node, prop); - if (cfg_node) { - ret = of_property_read_u32(cfg_node, "bws", - &cdesc->bws); -@@ -278,6 +278,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) - atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i), - cdesc->aws); - } -+ of_node_put(cfg_node); - } - - cdesc->probed = true; -diff --git a/drivers/dma/zx296702_dma.c b/drivers/dma/zx296702_dma.c -index 245d759d5ffc..6059d81e701a 100644 ---- a/drivers/dma/zx296702_dma.c -+++ b/drivers/dma/zx296702_dma.c -@@ -813,6 +813,7 @@ static int zx_dma_probe(struct platform_device *op) - INIT_LIST_HEAD(&d->slave.channels); - dma_cap_set(DMA_SLAVE, d->slave.cap_mask); - dma_cap_set(DMA_MEMCPY, d->slave.cap_mask); -+ dma_cap_set(DMA_CYCLIC, d->slave.cap_mask); - dma_cap_set(DMA_PRIVATE, d->slave.cap_mask); - d->slave.dev = &op->dev; - d->slave.device_free_chan_resources = zx_dma_free_chan_resources; -diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile -index ffd673615772..26412d2f8c98 100644 ---- a/drivers/gpu/drm/armada/Makefile -+++ b/drivers/gpu/drm/armada/Makefile -@@ -4,3 +4,5 @@ armada-y += armada_510.o - armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o - - obj-$(CONFIG_DRM_ARMADA) := armada.o -+ -+CFLAGS_armada_trace.o := -I$(src) -diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c -index 04de6fd88f8c..521b5bddb99c 100644 ---- a/drivers/gpu/drm/drm_mm.c -+++ b/drivers/gpu/drm/drm_mm.c -@@ -262,14 +262,12 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, - - BUG_ON(!hole_node->hole_follows || node->allocated); - -- if (adj_start < start) -- adj_start = start; -- if (adj_end > end) -- adj_end = end; -- - if (mm->color_adjust) - mm->color_adjust(hole_node, color, &adj_start, &adj_end); - -+ adj_start = max(adj_start, start); -+ adj_end = min(adj_end, end); -+ - if (flags & DRM_MM_CREATE_TOP) - adj_start = adj_end - size; - -@@ -475,17 +473,15 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_ - flags & DRM_MM_SEARCH_BELOW) { - u64 hole_size = adj_end - adj_start; - -- if (adj_start < start) -- adj_start = start; -- if (adj_end > end) -- adj_end = end; -- - if (mm->color_adjust) { - mm->color_adjust(entry, color, &adj_start, &adj_end); - if (adj_end <= adj_start) - continue; - } - -+ adj_start = max(adj_start, start); -+ adj_end = min(adj_end, end); -+ - if (!check_free_hole(adj_start, adj_end, size, alignment)) - continue; - -diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c -index fe89b6823217..263e97235ea0 100644 ---- a/drivers/iio/light/cm3232.c -+++ b/drivers/iio/light/cm3232.c -@@ -119,7 +119,7 @@ static int cm3232_reg_init(struct cm3232_chip *chip) - if (ret < 0) - dev_err(&chip->client->dev, "Error writing reg_cmd\n"); - -- return 0; -+ return ret; - } - - /** -diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c -index e397f1b0af09..9a99cee2665a 100644 ---- a/drivers/infiniband/ulp/srp/ib_srp.c -+++ b/drivers/infiniband/ulp/srp/ib_srp.c -@@ -670,12 +670,19 @@ static void srp_path_rec_completion(int status, - static int srp_lookup_path(struct srp_rdma_ch *ch) - { - struct srp_target_port *target = ch->target; -- int ret; -+ int ret = -ENODEV; - - ch->path.numb_path = 1; - - init_completion(&ch->done); - -+ /* -+ * Avoid that the SCSI host can be removed by srp_remove_target() -+ * before srp_path_rec_completion() is called. -+ */ -+ if (!scsi_host_get(target->scsi_host)) -+ goto out; -+ - ch->path_query_id = ib_sa_path_rec_get(&srp_sa_client, - target->srp_host->srp_dev->dev, - target->srp_host->port, -@@ -689,18 +696,24 @@ static int srp_lookup_path(struct srp_rdma_ch *ch) - GFP_KERNEL, - srp_path_rec_completion, - ch, &ch->path_query); -- if (ch->path_query_id < 0) -- return ch->path_query_id; -+ ret = ch->path_query_id; -+ if (ret < 0) -+ goto put; - - ret = wait_for_completion_interruptible(&ch->done); - if (ret < 0) -- return ret; -+ goto put; - -- if (ch->status < 0) -+ ret = ch->status; -+ if (ret < 0) - shost_printk(KERN_WARNING, target->scsi_host, - PFX "Path record query failed\n"); - -- return ch->status; -+put: -+ scsi_host_put(target->scsi_host); -+ -+out: -+ return ret; - } - - static int srp_send_req(struct srp_rdma_ch *ch, bool multich) -diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c -index eaabf3125846..c52131233ba7 100644 ---- a/drivers/infiniband/ulp/srpt/ib_srpt.c -+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c -@@ -3425,7 +3425,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name) - { - const char *p; - unsigned len, count, leading_zero_bytes; -- int ret, rc; -+ int ret; - - p = name; - if (strncasecmp(p, "0x", 2) == 0) -@@ -3437,10 +3437,9 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name) - count = min(len / 2, 16U); - leading_zero_bytes = 16 - count; - memset(i_port_id, 0, leading_zero_bytes); -- rc = hex2bin(i_port_id + leading_zero_bytes, p, count); -- if (rc < 0) -- pr_debug("hex2bin failed for srpt_parse_i_port_id: %d\n", rc); -- ret = 0; -+ ret = hex2bin(i_port_id + leading_zero_bytes, p, count); -+ if (ret < 0) -+ pr_debug("hex2bin failed for srpt_parse_i_port_id: %d\n", ret); - out: - return ret; - } -diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c -index 8eeab72b93e2..ea47980949ef 100644 ---- a/drivers/md/bcache/alloc.c -+++ b/drivers/md/bcache/alloc.c -@@ -406,7 +406,8 @@ long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait) - - finish_wait(&ca->set->bucket_wait, &w); - out: -- wake_up_process(ca->alloc_thread); -+ if (ca->alloc_thread) -+ wake_up_process(ca->alloc_thread); - - trace_bcache_alloc(ca, reserve); - -diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c -index cdceefd0e57d..2ec7f90e3455 100644 ---- a/drivers/md/dm-bufio.c -+++ b/drivers/md/dm-bufio.c -@@ -928,7 +928,8 @@ static void __get_memory_limit(struct dm_bufio_client *c, - buffers = c->minimum_buffers; - - *limit_buffers = buffers; -- *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100; -+ *threshold_buffers = mult_frac(buffers, -+ DM_BUFIO_WRITEBACK_PERCENT, 100); - } - - /* -@@ -1829,19 +1830,15 @@ static int __init dm_bufio_init(void) - memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches); - memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names); - -- mem = (__u64)((totalram_pages - totalhigh_pages) * -- DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT; -+ mem = (__u64)mult_frac(totalram_pages - totalhigh_pages, -+ DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT; - - if (mem > ULONG_MAX) - mem = ULONG_MAX; - - #ifdef CONFIG_MMU -- /* -- * Get the size of vmalloc space the same way as VMALLOC_TOTAL -- * in fs/proc/internal.h -- */ -- if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100) -- mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100; -+ if (mem > mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100)) -+ mem = mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100); - #endif - - dm_bufio_default_cache_size = mem; -diff --git a/drivers/md/dm.c b/drivers/md/dm.c -index 320eb3c4bb6b..9ec6948e3b8b 100644 ---- a/drivers/md/dm.c -+++ b/drivers/md/dm.c -@@ -3507,11 +3507,15 @@ struct mapped_device *dm_get_from_kobject(struct kobject *kobj) - - md = container_of(kobj, struct mapped_device, kobj_holder.kobj); - -- if (test_bit(DMF_FREEING, &md->flags) || -- dm_deleting_md(md)) -- return NULL; -- -+ spin_lock(&_minor_lock); -+ if (test_bit(DMF_FREEING, &md->flags) || dm_deleting_md(md)) { -+ md = NULL; -+ goto out; -+ } - dm_get(md); -+out: -+ spin_unlock(&_minor_lock); -+ - return md; - } - -diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c -index efc21b1da211..ca107033e429 100644 ---- a/drivers/media/rc/ir-lirc-codec.c -+++ b/drivers/media/rc/ir-lirc-codec.c -@@ -286,11 +286,14 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, - if (!dev->max_timeout) - return -ENOSYS; - -+ /* Check for multiply overflow */ -+ if (val > U32_MAX / 1000) -+ return -EINVAL; -+ - tmp = val * 1000; - -- if (tmp < dev->min_timeout || -- tmp > dev->max_timeout) -- return -EINVAL; -+ if (tmp < dev->min_timeout || tmp > dev->max_timeout) -+ return -EINVAL; - - dev->timeout = tmp; - break; -diff --git a/drivers/media/usb/as102/as102_fw.c b/drivers/media/usb/as102/as102_fw.c -index 07d08c49f4d4..b2e16bb67572 100644 ---- a/drivers/media/usb/as102/as102_fw.c -+++ b/drivers/media/usb/as102/as102_fw.c -@@ -101,18 +101,23 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, - unsigned char *cmd, - const struct firmware *firmware) { - -- struct as10x_fw_pkt_t fw_pkt; -+ struct as10x_fw_pkt_t *fw_pkt; - int total_read_bytes = 0, errno = 0; - unsigned char addr_has_changed = 0; - -+ fw_pkt = kmalloc(sizeof(*fw_pkt), GFP_KERNEL); -+ if (!fw_pkt) -+ return -ENOMEM; -+ -+ - for (total_read_bytes = 0; total_read_bytes < firmware->size; ) { - int read_bytes = 0, data_len = 0; - - /* parse intel hex line */ - read_bytes = parse_hex_line( - (u8 *) (firmware->data + total_read_bytes), -- fw_pkt.raw.address, -- fw_pkt.raw.data, -+ fw_pkt->raw.address, -+ fw_pkt->raw.data, - &data_len, - &addr_has_changed); - -@@ -122,28 +127,28 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, - /* detect the end of file */ - total_read_bytes += read_bytes; - if (total_read_bytes == firmware->size) { -- fw_pkt.u.request[0] = 0x00; -- fw_pkt.u.request[1] = 0x03; -+ fw_pkt->u.request[0] = 0x00; -+ fw_pkt->u.request[1] = 0x03; - - /* send EOF command */ - errno = bus_adap->ops->upload_fw_pkt(bus_adap, - (uint8_t *) -- &fw_pkt, 2, 0); -+ fw_pkt, 2, 0); - if (errno < 0) - goto error; - } else { - if (!addr_has_changed) { - /* prepare command to send */ -- fw_pkt.u.request[0] = 0x00; -- fw_pkt.u.request[1] = 0x01; -+ fw_pkt->u.request[0] = 0x00; -+ fw_pkt->u.request[1] = 0x01; - -- data_len += sizeof(fw_pkt.u.request); -- data_len += sizeof(fw_pkt.raw.address); -+ data_len += sizeof(fw_pkt->u.request); -+ data_len += sizeof(fw_pkt->raw.address); - - /* send cmd to device */ - errno = bus_adap->ops->upload_fw_pkt(bus_adap, - (uint8_t *) -- &fw_pkt, -+ fw_pkt, - data_len, - 0); - if (errno < 0) -@@ -152,6 +157,7 @@ static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap, - } - } - error: -+ kfree(fw_pkt); - return (errno == 0) ? total_read_bytes : errno; - } - -diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c -index 2c5f76d588ac..04ae21278440 100644 ---- a/drivers/media/usb/cx231xx/cx231xx-cards.c -+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c -@@ -1672,7 +1672,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, - nr = dev->devno; - - assoc_desc = udev->actconfig->intf_assoc[0]; -- if (assoc_desc->bFirstInterface != ifnum) { -+ if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) { - dev_err(d, "Not found matching IAD interface\n"); - retval = -ENODEV; - goto err_if; -diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c -index 8f8418d2ac4a..a0012c3cb4f6 100644 ---- a/drivers/net/ethernet/3com/typhoon.c -+++ b/drivers/net/ethernet/3com/typhoon.c -@@ -2366,9 +2366,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - * 4) Get the hardware address. - * 5) Put the card to sleep. - */ -- if (typhoon_reset(ioaddr, WaitSleep) < 0) { -+ err = typhoon_reset(ioaddr, WaitSleep); -+ if (err < 0) { - err_msg = "could not reset 3XP"; -- err = -EIO; - goto error_out_dma; - } - -@@ -2382,24 +2382,25 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - typhoon_init_interface(tp); - typhoon_init_rings(tp); - -- if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { -+ err = typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST); -+ if (err < 0) { - err_msg = "cannot boot 3XP sleep image"; -- err = -EIO; - goto error_out_reset; - } - - INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS); -- if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) { -+ err = typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp); -+ if (err < 0) { - err_msg = "cannot read MAC address"; -- err = -EIO; - goto error_out_reset; - } - - *(__be16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1)); - *(__be32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2)); - -- if(!is_valid_ether_addr(dev->dev_addr)) { -+ if (!is_valid_ether_addr(dev->dev_addr)) { - err_msg = "Could not obtain valid ethernet address, aborting"; -+ err = -EIO; - goto error_out_reset; - } - -@@ -2407,7 +2408,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - * later when we print out the version reported. - */ - INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS); -- if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) { -+ err = typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp); -+ if (err < 0) { - err_msg = "Could not get Sleep Image version"; - goto error_out_reset; - } -@@ -2424,9 +2426,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - if(xp_resp[0].numDesc != 0) - tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET; - -- if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) { -+ err = typhoon_sleep(tp, PCI_D3hot, 0); -+ if (err < 0) { - err_msg = "cannot put adapter to sleep"; -- err = -EIO; - goto error_out_reset; - } - -@@ -2449,7 +2451,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - dev->features = dev->hw_features | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_RXCSUM; - -- if(register_netdev(dev) < 0) { -+ err = register_netdev(dev); -+ if (err < 0) { - err_msg = "unable to register netdev"; - goto error_out_reset; - } -diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c -index e59d7c283cd4..645ace74429e 100644 ---- a/drivers/net/ethernet/intel/e1000e/mac.c -+++ b/drivers/net/ethernet/intel/e1000e/mac.c -@@ -410,6 +410,9 @@ void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. -+ * -+ * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link -+ * up). - **/ - s32 e1000e_check_for_copper_link(struct e1000_hw *hw) - { -@@ -423,7 +426,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) -- return 0; -+ return 1; - - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex -@@ -461,10 +464,12 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw) - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); -- if (ret_val) -+ if (ret_val) { - e_dbg("Error configuring flow control\n"); -+ return ret_val; -+ } - -- return ret_val; -+ return 1; - } - - /** -diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c -index 80ec587d510e..5205f1ebe381 100644 ---- a/drivers/net/ethernet/intel/e1000e/netdev.c -+++ b/drivers/net/ethernet/intel/e1000e/netdev.c -@@ -5017,7 +5017,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) - case e1000_media_type_copper: - if (hw->mac.get_link_status) { - ret_val = hw->mac.ops.check_for_link(hw); -- link_active = !hw->mac.get_link_status; -+ link_active = ret_val > 0; - } else { - link_active = true; - } -@@ -5035,7 +5035,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter) - break; - } - -- if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && -+ if ((ret_val == -E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && - (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { - /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ - e_info("Gigabit has been disabled, downgrading speed\n"); -diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c -index de13aeacae97..8e674a0988b0 100644 ---- a/drivers/net/ethernet/intel/e1000e/phy.c -+++ b/drivers/net/ethernet/intel/e1000e/phy.c -@@ -1744,6 +1744,7 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - s32 ret_val = 0; - u16 i, phy_status; - -+ *success = false; - for (i = 0; i < iterations; i++) { - /* Some PHYs require the MII_BMSR register to be read - * twice due to the link bit being sticky. No harm doing -@@ -1763,16 +1764,16 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; -- if (phy_status & BMSR_LSTATUS) -+ if (phy_status & BMSR_LSTATUS) { -+ *success = true; - break; -+ } - if (usec_interval >= 1000) - msleep(usec_interval / 1000); - else - udelay(usec_interval); - } - -- *success = (i < iterations); -- - return ret_val; - } - -diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c -index 09281558bfbc..c21fa56afd7c 100644 ---- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c -+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c -@@ -1226,7 +1226,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector, - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->flags & FM10K_TXD_FLAG_DONE)) -diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c -index 4edbab6ca7ef..b5b228c9a030 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_main.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c -@@ -3595,7 +3595,7 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if the descriptor isn't done, no work yet to do */ - if (!(eop_desc->cmd_type_offset_bsz & -diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c -index 26c55bba4bf3..6dcc3854844d 100644 ---- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c -+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c -@@ -663,7 +663,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* we have caught up to head, no work left to do */ - if (tx_head == tx_desc) -diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c -index 39db70a597ed..1ed27fcd5031 100644 ---- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c -+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c -@@ -172,7 +172,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* we have caught up to head, no work left to do */ - if (tx_head == tx_desc) -diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c -index ff6e57d788eb..c55552c3d2f9 100644 ---- a/drivers/net/ethernet/intel/igb/igb_main.c -+++ b/drivers/net/ethernet/intel/igb/igb_main.c -@@ -6433,7 +6433,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) -diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c -index 297af801f051..519b72c41888 100644 ---- a/drivers/net/ethernet/intel/igbvf/netdev.c -+++ b/drivers/net/ethernet/intel/igbvf/netdev.c -@@ -809,7 +809,7 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring) - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD))) -diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -index 83645d8503d4..a5b443171b8b 100644 ---- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c -@@ -1114,7 +1114,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) -diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -index 592ff237d692..50bbad37d640 100644 ---- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c -@@ -312,7 +312,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, - break; - - /* prevent any other reads prior to eop_desc */ -- read_barrier_depends(); -+ smp_rmb(); - - /* if DD is not set pending work has not been completed */ - if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) -diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c -index 05de75360fa4..ee638cb8b48f 100644 ---- a/drivers/net/wireless/ath/ath10k/core.c -+++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -548,8 +548,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) - "boot get otp board id result 0x%08x board_id %d chip_id %d\n", - result, board_id, chip_id); - -- if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0) -+ if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || -+ (board_id == 0)) { -+ ath10k_warn(ar, "board id is not exist in otp, ignore it\n"); - return -EOPNOTSUPP; -+ } - - ar->id.bmi_ids_valid = true; - ar->id.bmi_board_id = board_id; -diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c -index 6decf4a95ce1..bed8d89fe3a0 100644 ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1127,6 +1127,36 @@ static int ath10k_monitor_recalc(struct ath10k *ar) - return ath10k_monitor_stop(ar); - } - -+static bool ath10k_mac_can_set_cts_prot(struct ath10k_vif *arvif) -+{ -+ struct ath10k *ar = arvif->ar; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ if (!arvif->is_started) { -+ ath10k_dbg(ar, ATH10K_DBG_MAC, "defer cts setup, vdev is not ready yet\n"); -+ return false; -+ } -+ -+ return true; -+} -+ -+static int ath10k_mac_set_cts_prot(struct ath10k_vif *arvif) -+{ -+ struct ath10k *ar = arvif->ar; -+ u32 vdev_param; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ vdev_param = ar->wmi.vdev_param->protection_mode; -+ -+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_protection %d\n", -+ arvif->vdev_id, arvif->use_cts_prot); -+ -+ return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, -+ arvif->use_cts_prot ? 1 : 0); -+} -+ - static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) - { - struct ath10k *ar = arvif->ar; -@@ -4180,7 +4210,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) - lockdep_assert_held(&ar->conf_mutex); - - list_for_each_entry(arvif, &ar->arvifs, list) { -- WARN_ON(arvif->txpower < 0); -+ if (arvif->txpower <= 0) -+ continue; - - if (txpower == -1) - txpower = arvif->txpower; -@@ -4188,8 +4219,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar) - txpower = min(txpower, arvif->txpower); - } - -- if (WARN_ON(txpower == -1)) -- return -EINVAL; -+ if (txpower == -1) -+ return 0; - - ret = ath10k_mac_txpower_setup(ar, txpower); - if (ret) { -@@ -4787,20 +4818,18 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - arvif->use_cts_prot = info->use_cts_prot; -- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n", -- arvif->vdev_id, info->use_cts_prot); - - ret = ath10k_recalc_rtscts_prot(arvif); - if (ret) - ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", - arvif->vdev_id, ret); - -- vdev_param = ar->wmi.vdev_param->protection_mode; -- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, -- info->use_cts_prot ? 1 : 0); -- if (ret) -- ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", -- info->use_cts_prot, arvif->vdev_id, ret); -+ if (ath10k_mac_can_set_cts_prot(arvif)) { -+ ret = ath10k_mac_set_cts_prot(arvif); -+ if (ret) -+ ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", -+ arvif->vdev_id, ret); -+ } - } - - if (changed & BSS_CHANGED_ERP_SLOT) { -@@ -6712,6 +6741,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, - arvif->is_up = true; - } - -+ if (ath10k_mac_can_set_cts_prot(arvif)) { -+ ret = ath10k_mac_set_cts_prot(arvif); -+ if (ret) -+ ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n", -+ arvif->vdev_id, ret); -+ } -+ - mutex_unlock(&ar->conf_mutex); - return 0; - -diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c -index 6fbd17b69469..02eea3c3b5d3 100644 ---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c -+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c -@@ -1105,8 +1105,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, - struct ath10k_fw_stats_pdev *dst; - - src = data; -- if (data_len < sizeof(*src)) -+ if (data_len < sizeof(*src)) { -+ kfree(tb); - return -EPROTO; -+ } - - data += sizeof(*src); - data_len -= sizeof(*src); -@@ -1126,8 +1128,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, - struct ath10k_fw_stats_vdev *dst; - - src = data; -- if (data_len < sizeof(*src)) -+ if (data_len < sizeof(*src)) { -+ kfree(tb); - return -EPROTO; -+ } - - data += sizeof(*src); - data_len -= sizeof(*src); -@@ -1145,8 +1149,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, - struct ath10k_fw_stats_peer *dst; - - src = data; -- if (data_len < sizeof(*src)) -+ if (data_len < sizeof(*src)) { -+ kfree(tb); - return -EPROTO; -+ } - - data += sizeof(*src); - data_len -= sizeof(*src); -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c -index 0708eedd9671..1c69e8140d9d 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c -@@ -664,7 +664,7 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; -- -+ bool rtstatus; - u32 totalpacketlen; - u8 u1rsvdpageloc[5] = { 0 }; - bool b_dlok = false; -@@ -727,7 +727,9 @@ void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - -- b_dlok = true; -+ rtstatus = rtl_cmd_send_packet(hw, skb); -+ if (rtstatus) -+ b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , -diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -index bbb789f8990b..738d541a2255 100644 ---- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c -@@ -1377,6 +1377,7 @@ static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw) - - ppsc->wakeup_reason = 0; - -+ do_gettimeofday(&ts); - rtlhal->last_suspend_sec = ts.tv_sec; - - switch (fw_reason) { -diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c -index 96526dcfdd37..ff7b9632ad61 100644 ---- a/drivers/nvdimm/label.c -+++ b/drivers/nvdimm/label.c -@@ -823,7 +823,7 @@ static int init_labels(struct nd_mapping *nd_mapping, int num_labels) - nsindex = to_namespace_index(ndd, 0); - memset(nsindex, 0, ndd->nsarea.config_size); - for (i = 0; i < 2; i++) { -- int rc = nd_label_write_index(ndd, i, i*2, ND_NSINDEX_INIT); -+ int rc = nd_label_write_index(ndd, i, 3 - i, ND_NSINDEX_INIT); - - if (rc) - return rc; -diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c -index aae7379af4e4..c2184104b789 100644 ---- a/drivers/nvdimm/namespace_devs.c -+++ b/drivers/nvdimm/namespace_devs.c -@@ -1305,7 +1305,7 @@ static umode_t namespace_visible(struct kobject *kobj, - if (a == &dev_attr_resource.attr) { - if (is_namespace_blk(dev)) - return 0; -- return a->mode; -+ return 0400; - } - - if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { -diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c -index b83df942794f..193ac13de49b 100644 ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -1414,8 +1414,16 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) - - static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) - { -- if (hpp) -- dev_warn(&dev->dev, "PCI-X settings not supported\n"); -+ int pos; -+ -+ if (!hpp) -+ return; -+ -+ pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); -+ if (!pos) -+ return; -+ -+ dev_warn(&dev->dev, "PCI-X settings not supported\n"); - } - - static bool pcie_root_rcb_set(struct pci_dev *dev) -@@ -1441,6 +1449,9 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) - if (!hpp) - return; - -+ if (!pci_is_pcie(dev)) -+ return; -+ - if (hpp->revision > 1) { - dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", - hpp->revision); -diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 8b9c2a38d1cc..b0a24dedd1ed 100644 ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -315,6 +315,7 @@ config SPI_FSL_SPI - config SPI_FSL_DSPI - tristate "Freescale DSPI controller" - select REGMAP_MMIO -+ depends on HAS_DMA - depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST - help - This enables support for the Freescale DSPI controller in master -diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c -index e8d0ff2d5c9b..808d6ebf6c94 100644 ---- a/drivers/staging/iio/cdc/ad7150.c -+++ b/drivers/staging/iio/cdc/ad7150.c -@@ -272,7 +272,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev, - error_ret: - mutex_unlock(&chip->state_lock); - -- return 0; -+ return ret; - } - - static int ad7150_read_event_value(struct iio_dev *indio_dev, -diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c -index fd493412b172..bb73401f5761 100644 ---- a/drivers/target/iscsi/iscsi_target.c -+++ b/drivers/target/iscsi/iscsi_target.c -@@ -1923,12 +1923,14 @@ attach: - - if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { - int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); -- if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) -+ if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) { - out_of_order_cmdsn = 1; -- else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) -+ } else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { -+ target_put_sess_cmd(&cmd->se_cmd); - return 0; -- else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) -+ } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { - return -1; -+ } - } - iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); - -diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c -index a42054edd427..37abf881ca75 100644 ---- a/drivers/target/target_core_transport.c -+++ b/drivers/target/target_core_transport.c -@@ -1970,6 +1970,8 @@ static void target_restart_delayed_cmds(struct se_device *dev) - list_del(&cmd->se_delayed_node); - spin_unlock(&dev->delayed_cmd_lock); - -+ cmd->transport_state |= CMD_T_SENT; -+ - __target_execute_cmd(cmd, true); - - if (cmd->sam_task_attr == TCM_ORDERED_TAG) -@@ -2007,6 +2009,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd) - pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", - dev->dev_cur_ordered_id); - } -+ cmd->se_cmd_flags &= ~SCF_TASK_ATTR_SET; -+ - restart: - target_restart_delayed_cmds(dev); - } -diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c -index e4110d6de0b5..da6cc25baaef 100644 ---- a/drivers/vhost/scsi.c -+++ b/drivers/vhost/scsi.c -@@ -703,6 +703,7 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, - struct scatterlist *sg, int sg_count) - { - size_t off = iter->iov_offset; -+ struct scatterlist *p = sg; - int i, ret; - - for (i = 0; i < iter->nr_segs; i++) { -@@ -711,8 +712,8 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write, - - ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write); - if (ret < 0) { -- for (i = 0; i < sg_count; i++) { -- struct page *page = sg_page(&sg[i]); -+ while (p < sg) { -+ struct page *page = sg_page(p++); - if (page) - put_page(page); - } -diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c -index 0e0eb10f82a0..816a0e08ef10 100644 ---- a/drivers/xen/xenbus/xenbus_dev_frontend.c -+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c -@@ -316,7 +316,7 @@ static int xenbus_write_transaction(unsigned msg_type, - rc = -ENOMEM; - goto out; - } -- } else if (msg_type == XS_TRANSACTION_END) { -+ } else if (u->u.msg.tx_id != 0) { - list_for_each_entry(trans, &u->transactions, list) - if (trans->handle.id == u->u.msg.tx_id) - break; -diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c -index 511078586fa1..73f1d1b3a51c 100644 ---- a/fs/9p/vfs_inode.c -+++ b/fs/9p/vfs_inode.c -@@ -483,6 +483,9 @@ static int v9fs_test_inode(struct inode *inode, void *data) - - if (v9inode->qid.type != st->qid.type) - return 0; -+ -+ if (v9inode->qid.path != st->qid.path) -+ return 0; - return 1; - } - -diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c -index cb899af1babc..0b88744c6446 100644 ---- a/fs/9p/vfs_inode_dotl.c -+++ b/fs/9p/vfs_inode_dotl.c -@@ -87,6 +87,9 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data) - - if (v9inode->qid.type != st->qid.type) - return 0; -+ -+ if (v9inode->qid.path != st->qid.path) -+ return 0; - return 1; - } - -diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c -index 35b755e79c2d..fe6e7050fe50 100644 ---- a/fs/autofs4/waitq.c -+++ b/fs/autofs4/waitq.c -@@ -87,7 +87,8 @@ static int autofs4_write(struct autofs_sb_info *sbi, - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - -- return (bytes > 0); -+ /* if 'wr' returned 0 (impossible) we assume -EIO (safe) */ -+ return bytes == 0 ? 0 : wr < 0 ? wr : -EIO; - } - - static void autofs4_notify_daemon(struct autofs_sb_info *sbi, -@@ -101,6 +102,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, - } pkt; - struct file *pipe = NULL; - size_t pktsz; -+ int ret; - - DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", - (unsigned long) wq->wait_queue_token, wq->name.len, wq->name.name, type); -@@ -173,7 +175,18 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, - mutex_unlock(&sbi->wq_mutex); - - if (autofs4_write(sbi, pipe, &pkt, pktsz)) -+ switch (ret = autofs4_write(sbi, pipe, &pkt, pktsz)) { -+ case 0: -+ break; -+ case -ENOMEM: -+ case -ERESTARTSYS: -+ /* Just fail this one */ -+ autofs4_wait_release(sbi, wq->wait_queue_token, ret); -+ break; -+ default: - autofs4_catatonic_mode(sbi); -+ break; -+ } - fput(pipe); - } - -diff --git a/fs/btrfs/uuid-tree.c b/fs/btrfs/uuid-tree.c -index 778282944530..837a9a8d579e 100644 ---- a/fs/btrfs/uuid-tree.c -+++ b/fs/btrfs/uuid-tree.c -@@ -348,7 +348,5 @@ skip: - - out: - btrfs_free_path(path); -- if (ret) -- btrfs_warn(fs_info, "btrfs_uuid_tree_iterate failed %d", ret); -- return 0; -+ return ret; - } -diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c -index 286f10b0363b..4f457d5c4933 100644 ---- a/fs/ecryptfs/messaging.c -+++ b/fs/ecryptfs/messaging.c -@@ -442,15 +442,16 @@ void ecryptfs_release_messaging(void) - } - if (ecryptfs_daemon_hash) { - struct ecryptfs_daemon *daemon; -+ struct hlist_node *n; - int i; - - mutex_lock(&ecryptfs_daemon_hash_mux); - for (i = 0; i < (1 << ecryptfs_hash_bits); i++) { - int rc; - -- hlist_for_each_entry(daemon, -- &ecryptfs_daemon_hash[i], -- euid_chain) { -+ hlist_for_each_entry_safe(daemon, n, -+ &ecryptfs_daemon_hash[i], -+ euid_chain) { - rc = ecryptfs_exorcise_daemon(daemon); - if (rc) - printk(KERN_ERR "%s: Error whilst " -diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c -index 9a1bc638abce..9308fe4b66e6 100644 ---- a/fs/ext4/crypto_key.c -+++ b/fs/ext4/crypto_key.c -@@ -129,11 +129,9 @@ int ext4_get_encryption_info(struct inode *inode) - if (ei->i_crypt_info) - return 0; - -- if (!ext4_read_workqueue) { -- res = ext4_init_crypto(); -- if (res) -- return res; -- } -+ res = ext4_init_crypto(); -+ if (res) -+ return res; - - res = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION, - EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, -diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c -index 61d5bfc7318c..31a3e480d484 100644 ---- a/fs/ext4/extents.c -+++ b/fs/ext4/extents.c -@@ -4818,7 +4818,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, - } - - if (!(mode & FALLOC_FL_KEEP_SIZE) && -- offset + len > i_size_read(inode)) { -+ (offset + len > i_size_read(inode) || -+ offset + len > EXT4_I(inode)->i_disksize)) { - new_size = offset + len; - ret = inode_newsize_ok(inode, new_size); - if (ret) -@@ -4994,7 +4995,8 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) - } - - if (!(mode & FALLOC_FL_KEEP_SIZE) && -- offset + len > i_size_read(inode)) { -+ (offset + len > i_size_read(inode) || -+ offset + len > EXT4_I(inode)->i_disksize)) { - new_size = offset + len; - ret = inode_newsize_ok(inode, new_size); - if (ret) -diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h -index 0ac4c1f73fbd..25177e6bd603 100644 ---- a/fs/isofs/isofs.h -+++ b/fs/isofs/isofs.h -@@ -103,7 +103,7 @@ static inline unsigned int isonum_733(char *p) - /* Ignore bigendian datum due to broken mastering programs */ - return get_unaligned_le32(p); - } --extern int iso_date(char *, int); -+extern int iso_date(u8 *, int); - - struct inode; /* To make gcc happy */ - -diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h -index ed09e2b08637..f835976ce033 100644 ---- a/fs/isofs/rock.h -+++ b/fs/isofs/rock.h -@@ -65,7 +65,7 @@ struct RR_PL_s { - }; - - struct stamp { -- char time[7]; -+ __u8 time[7]; /* actually 6 unsigned, 1 signed */ - } __attribute__ ((packed)); - - struct RR_TF_s { -diff --git a/fs/isofs/util.c b/fs/isofs/util.c -index 005a15cfd30a..37860fea364d 100644 ---- a/fs/isofs/util.c -+++ b/fs/isofs/util.c -@@ -15,7 +15,7 @@ - * to GMT. Thus we should always be correct. - */ - --int iso_date(char * p, int flag) -+int iso_date(u8 *p, int flag) - { - int year, month, day, hour, minute, second, tz; - int crtime; -diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c -index 8e425f2c5ddd..6fef53f18dcf 100644 ---- a/fs/nfs/nfs4proc.c -+++ b/fs/nfs/nfs4proc.c -@@ -242,15 +242,12 @@ const u32 nfs4_fsinfo_bitmap[3] = { FATTR4_WORD0_MAXFILESIZE - }; - - const u32 nfs4_fs_locations_bitmap[3] = { -- FATTR4_WORD0_TYPE -- | FATTR4_WORD0_CHANGE -+ FATTR4_WORD0_CHANGE - | FATTR4_WORD0_SIZE - | FATTR4_WORD0_FSID - | FATTR4_WORD0_FILEID - | FATTR4_WORD0_FS_LOCATIONS, -- FATTR4_WORD1_MODE -- | FATTR4_WORD1_NUMLINKS -- | FATTR4_WORD1_OWNER -+ FATTR4_WORD1_OWNER - | FATTR4_WORD1_OWNER_GROUP - | FATTR4_WORD1_RAWDEV - | FATTR4_WORD1_SPACE_USED -@@ -6351,9 +6348,7 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, - struct page *page) - { - struct nfs_server *server = NFS_SERVER(dir); -- u32 bitmask[3] = { -- [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, -- }; -+ u32 bitmask[3]; - struct nfs4_fs_locations_arg args = { - .dir_fh = NFS_FH(dir), - .name = name, -@@ -6372,12 +6367,15 @@ static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, - - dprintk("%s: start\n", __func__); - -+ bitmask[0] = nfs4_fattr_bitmap[0] | FATTR4_WORD0_FS_LOCATIONS; -+ bitmask[1] = nfs4_fattr_bitmap[1]; -+ - /* Ask for the fileid of the absent filesystem if mounted_on_fileid - * is not supported */ - if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) -- bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; -+ bitmask[0] &= ~FATTR4_WORD0_FILEID; - else -- bitmask[0] |= FATTR4_WORD0_FILEID; -+ bitmask[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; - - nfs_fattr_init(&fs_locations->fattr); - fs_locations->server = server; -diff --git a/fs/nfs/super.c b/fs/nfs/super.c -index f1268280244e..3149f7e58d6f 100644 ---- a/fs/nfs/super.c -+++ b/fs/nfs/super.c -@@ -1322,7 +1322,7 @@ static int nfs_parse_mount_options(char *raw, - mnt->options |= NFS_OPTION_MIGRATION; - break; - case Opt_nomigration: -- mnt->options &= NFS_OPTION_MIGRATION; -+ mnt->options &= ~NFS_OPTION_MIGRATION; - break; - - /* -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index ca9ebc3242d3..421935f3d909 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -3829,7 +3829,8 @@ static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, statei - { - struct nfs4_stid *ret; - -- ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID); -+ ret = find_stateid_by_type(cl, s, -+ NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID); - if (!ret) - return NULL; - return delegstateid(ret); -@@ -3852,6 +3853,12 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open, - deleg = find_deleg_stateid(cl, &open->op_delegate_stateid); - if (deleg == NULL) - goto out; -+ if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) { -+ nfs4_put_stid(&deleg->dl_stid); -+ if (cl->cl_minorversion) -+ status = nfserr_deleg_revoked; -+ goto out; -+ } - flags = share_access_to_flags(open->op_share_access); - status = nfs4_check_delegmode(deleg, flags); - if (status) { -@@ -4696,6 +4703,16 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, - struct nfs4_stid **s, struct nfsd_net *nn) - { - __be32 status; -+ bool return_revoked = false; -+ -+ /* -+ * only return revoked delegations if explicitly asked. -+ * otherwise we report revoked or bad_stateid status. -+ */ -+ if (typemask & NFS4_REVOKED_DELEG_STID) -+ return_revoked = true; -+ else if (typemask & NFS4_DELEG_STID) -+ typemask |= NFS4_REVOKED_DELEG_STID; - - if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) - return nfserr_bad_stateid; -@@ -4710,6 +4727,12 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate, - *s = find_stateid_by_type(cstate->clp, stateid, typemask); - if (!*s) - return nfserr_bad_stateid; -+ if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) { -+ nfs4_put_stid(*s); -+ if (cstate->minorversion) -+ return nfserr_deleg_revoked; -+ return nfserr_bad_stateid; -+ } - return nfs_ok; - } - -diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c -index 2f27c935bd57..34c22fe4eca0 100644 ---- a/fs/nilfs2/segment.c -+++ b/fs/nilfs2/segment.c -@@ -1945,8 +1945,6 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, - "failed to get inode block.\n"); - return err; - } -- mark_buffer_dirty(ibh); -- nilfs_mdt_mark_dirty(ifile); - spin_lock(&nilfs->ns_inode_lock); - if (likely(!ii->i_bh)) - ii->i_bh = ibh; -@@ -1955,6 +1953,10 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, - goto retry; - } - -+ // Always redirty the buffer to avoid race condition -+ mark_buffer_dirty(ii->i_bh); -+ nilfs_mdt_mark_dirty(ifile); -+ - clear_bit(NILFS_I_QUEUED, &ii->i_state); - set_bit(NILFS_I_BUSY, &ii->i_state); - list_move_tail(&ii->i_dirty, &sci->sc_dirty_files); -diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h -index 5664ca07c9c7..a01a076ea060 100644 ---- a/include/trace/events/sunrpc.h -+++ b/include/trace/events/sunrpc.h -@@ -455,20 +455,22 @@ TRACE_EVENT(svc_recv, - TP_ARGS(rqst, status), - - TP_STRUCT__entry( -- __field(struct sockaddr *, addr) - __field(__be32, xid) - __field(int, status) - __field(unsigned long, flags) -+ __dynamic_array(unsigned char, addr, rqst->rq_addrlen) - ), - - TP_fast_assign( -- __entry->addr = (struct sockaddr *)&rqst->rq_addr; - __entry->xid = status > 0 ? rqst->rq_xid : 0; - __entry->status = status; - __entry->flags = rqst->rq_flags; -+ memcpy(__get_dynamic_array(addr), -+ &rqst->rq_addr, rqst->rq_addrlen); - ), - -- TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", __entry->addr, -+ TP_printk("addr=%pIScp xid=0x%x status=%d flags=%s", -+ (struct sockaddr *)__get_dynamic_array(addr), - be32_to_cpu(__entry->xid), __entry->status, - show_rqstp_flags(__entry->flags)) - ); -@@ -480,22 +482,23 @@ DECLARE_EVENT_CLASS(svc_rqst_status, - TP_ARGS(rqst, status), - - TP_STRUCT__entry( -- __field(struct sockaddr *, addr) - __field(__be32, xid) -- __field(int, dropme) - __field(int, status) - __field(unsigned long, flags) -+ __dynamic_array(unsigned char, addr, rqst->rq_addrlen) - ), - - TP_fast_assign( -- __entry->addr = (struct sockaddr *)&rqst->rq_addr; - __entry->xid = rqst->rq_xid; - __entry->status = status; - __entry->flags = rqst->rq_flags; -+ memcpy(__get_dynamic_array(addr), -+ &rqst->rq_addr, rqst->rq_addrlen); - ), - - TP_printk("addr=%pIScp rq_xid=0x%x status=%d flags=%s", -- __entry->addr, be32_to_cpu(__entry->xid), -+ (struct sockaddr *)__get_dynamic_array(addr), -+ be32_to_cpu(__entry->xid), - __entry->status, show_rqstp_flags(__entry->flags)) - ); - -diff --git a/kernel/sched/core.c b/kernel/sched/core.c -index b5d372083624..15874a85ebcf 100644 ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -600,8 +600,7 @@ void resched_cpu(int cpu) - struct rq *rq = cpu_rq(cpu); - unsigned long flags; - -- if (!raw_spin_trylock_irqsave(&rq->lock, flags)) -- return; -+ raw_spin_lock_irqsave(&rq->lock, flags); - resched_curr(rq); - raw_spin_unlock_irqrestore(&rq->lock, flags); - } -@@ -5908,6 +5907,12 @@ static int init_rootdomain(struct root_domain *rd) - if (!zalloc_cpumask_var(&rd->rto_mask, GFP_KERNEL)) - goto free_dlo_mask; - -+#ifdef HAVE_RT_PUSH_IPI -+ rd->rto_cpu = -1; -+ raw_spin_lock_init(&rd->rto_lock); -+ init_irq_work(&rd->rto_push_work, rto_push_irq_work_func); -+#endif -+ - init_dl_bw(&rd->dl_bw); - if (cpudl_init(&rd->cpudl) != 0) - goto free_dlo_mask; -diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c -index 78ae5c1d9412..faa75afcb7fe 100644 ---- a/kernel/sched/rt.c -+++ b/kernel/sched/rt.c -@@ -64,10 +64,6 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b) - raw_spin_unlock(&rt_b->rt_runtime_lock); - } - --#if defined(CONFIG_SMP) && defined(HAVE_RT_PUSH_IPI) --static void push_irq_work_func(struct irq_work *work); --#endif -- - void init_rt_rq(struct rt_rq *rt_rq) - { - struct rt_prio_array *array; -@@ -87,13 +83,6 @@ void init_rt_rq(struct rt_rq *rt_rq) - rt_rq->rt_nr_migratory = 0; - rt_rq->overloaded = 0; - plist_head_init(&rt_rq->pushable_tasks); -- --#ifdef HAVE_RT_PUSH_IPI -- rt_rq->push_flags = 0; -- rt_rq->push_cpu = nr_cpu_ids; -- raw_spin_lock_init(&rt_rq->push_lock); -- init_irq_work(&rt_rq->push_work, push_irq_work_func); --#endif - #endif /* CONFIG_SMP */ - /* We start is dequeued state, because no RT tasks are queued */ - rt_rq->rt_queued = 0; -@@ -1802,160 +1791,166 @@ static void push_rt_tasks(struct rq *rq) - } - - #ifdef HAVE_RT_PUSH_IPI -+ - /* -- * The search for the next cpu always starts at rq->cpu and ends -- * when we reach rq->cpu again. It will never return rq->cpu. -- * This returns the next cpu to check, or nr_cpu_ids if the loop -- * is complete. -+ * When a high priority task schedules out from a CPU and a lower priority -+ * task is scheduled in, a check is made to see if there's any RT tasks -+ * on other CPUs that are waiting to run because a higher priority RT task -+ * is currently running on its CPU. In this case, the CPU with multiple RT -+ * tasks queued on it (overloaded) needs to be notified that a CPU has opened -+ * up that may be able to run one of its non-running queued RT tasks. -+ * -+ * All CPUs with overloaded RT tasks need to be notified as there is currently -+ * no way to know which of these CPUs have the highest priority task waiting -+ * to run. Instead of trying to take a spinlock on each of these CPUs, -+ * which has shown to cause large latency when done on machines with many -+ * CPUs, sending an IPI to the CPUs to have them push off the overloaded -+ * RT tasks waiting to run. -+ * -+ * Just sending an IPI to each of the CPUs is also an issue, as on large -+ * count CPU machines, this can cause an IPI storm on a CPU, especially -+ * if its the only CPU with multiple RT tasks queued, and a large number -+ * of CPUs scheduling a lower priority task at the same time. -+ * -+ * Each root domain has its own irq work function that can iterate over -+ * all CPUs with RT overloaded tasks. Since all CPUs with overloaded RT -+ * tassk must be checked if there's one or many CPUs that are lowering -+ * their priority, there's a single irq work iterator that will try to -+ * push off RT tasks that are waiting to run. -+ * -+ * When a CPU schedules a lower priority task, it will kick off the -+ * irq work iterator that will jump to each CPU with overloaded RT tasks. -+ * As it only takes the first CPU that schedules a lower priority task -+ * to start the process, the rto_start variable is incremented and if -+ * the atomic result is one, then that CPU will try to take the rto_lock. -+ * This prevents high contention on the lock as the process handles all -+ * CPUs scheduling lower priority tasks. -+ * -+ * All CPUs that are scheduling a lower priority task will increment the -+ * rt_loop_next variable. This will make sure that the irq work iterator -+ * checks all RT overloaded CPUs whenever a CPU schedules a new lower -+ * priority task, even if the iterator is in the middle of a scan. Incrementing -+ * the rt_loop_next will cause the iterator to perform another scan. - * -- * rq->rt.push_cpu holds the last cpu returned by this function, -- * or if this is the first instance, it must hold rq->cpu. - */ - static int rto_next_cpu(struct rq *rq) - { -- int prev_cpu = rq->rt.push_cpu; -+ struct root_domain *rd = rq->rd; -+ int next; - int cpu; - -- cpu = cpumask_next(prev_cpu, rq->rd->rto_mask); -- - /* -- * If the previous cpu is less than the rq's CPU, then it already -- * passed the end of the mask, and has started from the beginning. -- * We end if the next CPU is greater or equal to rq's CPU. -+ * When starting the IPI RT pushing, the rto_cpu is set to -1, -+ * rt_next_cpu() will simply return the first CPU found in -+ * the rto_mask. -+ * -+ * If rto_next_cpu() is called with rto_cpu is a valid cpu, it -+ * will return the next CPU found in the rto_mask. -+ * -+ * If there are no more CPUs left in the rto_mask, then a check is made -+ * against rto_loop and rto_loop_next. rto_loop is only updated with -+ * the rto_lock held, but any CPU may increment the rto_loop_next -+ * without any locking. - */ -- if (prev_cpu < rq->cpu) { -- if (cpu >= rq->cpu) -- return nr_cpu_ids; -+ for (;;) { - -- } else if (cpu >= nr_cpu_ids) { -- /* -- * We passed the end of the mask, start at the beginning. -- * If the result is greater or equal to the rq's CPU, then -- * the loop is finished. -- */ -- cpu = cpumask_first(rq->rd->rto_mask); -- if (cpu >= rq->cpu) -- return nr_cpu_ids; -- } -- rq->rt.push_cpu = cpu; -+ /* When rto_cpu is -1 this acts like cpumask_first() */ -+ cpu = cpumask_next(rd->rto_cpu, rd->rto_mask); - -- /* Return cpu to let the caller know if the loop is finished or not */ -- return cpu; --} -+ rd->rto_cpu = cpu; - --static int find_next_push_cpu(struct rq *rq) --{ -- struct rq *next_rq; -- int cpu; -+ if (cpu < nr_cpu_ids) -+ return cpu; - -- while (1) { -- cpu = rto_next_cpu(rq); -- if (cpu >= nr_cpu_ids) -- break; -- next_rq = cpu_rq(cpu); -+ rd->rto_cpu = -1; - -- /* Make sure the next rq can push to this rq */ -- if (next_rq->rt.highest_prio.next < rq->rt.highest_prio.curr) -+ /* -+ * ACQUIRE ensures we see the @rto_mask changes -+ * made prior to the @next value observed. -+ * -+ * Matches WMB in rt_set_overload(). -+ */ -+ next = atomic_read_acquire(&rd->rto_loop_next); -+ -+ if (rd->rto_loop == next) - break; -+ -+ rd->rto_loop = next; - } - -- return cpu; -+ return -1; -+} -+ -+static inline bool rto_start_trylock(atomic_t *v) -+{ -+ return !atomic_cmpxchg_acquire(v, 0, 1); - } - --#define RT_PUSH_IPI_EXECUTING 1 --#define RT_PUSH_IPI_RESTART 2 -+static inline void rto_start_unlock(atomic_t *v) -+{ -+ atomic_set_release(v, 0); -+} - - static void tell_cpu_to_push(struct rq *rq) - { -- int cpu; -+ int cpu = -1; - -- if (rq->rt.push_flags & RT_PUSH_IPI_EXECUTING) { -- raw_spin_lock(&rq->rt.push_lock); -- /* Make sure it's still executing */ -- if (rq->rt.push_flags & RT_PUSH_IPI_EXECUTING) { -- /* -- * Tell the IPI to restart the loop as things have -- * changed since it started. -- */ -- rq->rt.push_flags |= RT_PUSH_IPI_RESTART; -- raw_spin_unlock(&rq->rt.push_lock); -- return; -- } -- raw_spin_unlock(&rq->rt.push_lock); -- } -+ /* Keep the loop going if the IPI is currently active */ -+ atomic_inc(&rq->rd->rto_loop_next); - -- /* When here, there's no IPI going around */ -- -- rq->rt.push_cpu = rq->cpu; -- cpu = find_next_push_cpu(rq); -- if (cpu >= nr_cpu_ids) -+ /* Only one CPU can initiate a loop at a time */ -+ if (!rto_start_trylock(&rq->rd->rto_loop_start)) - return; - -- rq->rt.push_flags = RT_PUSH_IPI_EXECUTING; -+ raw_spin_lock(&rq->rd->rto_lock); -+ -+ /* -+ * The rto_cpu is updated under the lock, if it has a valid cpu -+ * then the IPI is still running and will continue due to the -+ * update to loop_next, and nothing needs to be done here. -+ * Otherwise it is finishing up and an ipi needs to be sent. -+ */ -+ if (rq->rd->rto_cpu < 0) -+ cpu = rto_next_cpu(rq); -+ -+ raw_spin_unlock(&rq->rd->rto_lock); - -- irq_work_queue_on(&rq->rt.push_work, cpu); -+ rto_start_unlock(&rq->rd->rto_loop_start); -+ -+ if (cpu >= 0) -+ irq_work_queue_on(&rq->rd->rto_push_work, cpu); - } - - /* Called from hardirq context */ --static void try_to_push_tasks(void *arg) -+void rto_push_irq_work_func(struct irq_work *work) - { -- struct rt_rq *rt_rq = arg; -- struct rq *rq, *src_rq; -- int this_cpu; -+ struct rq *rq; - int cpu; - -- this_cpu = rt_rq->push_cpu; -+ rq = this_rq(); - -- /* Paranoid check */ -- BUG_ON(this_cpu != smp_processor_id()); -- -- rq = cpu_rq(this_cpu); -- src_rq = rq_of_rt_rq(rt_rq); -- --again: -+ /* -+ * We do not need to grab the lock to check for has_pushable_tasks. -+ * When it gets updated, a check is made if a push is possible. -+ */ - if (has_pushable_tasks(rq)) { - raw_spin_lock(&rq->lock); -- push_rt_task(rq); -+ push_rt_tasks(rq); - raw_spin_unlock(&rq->lock); - } - -- /* Pass the IPI to the next rt overloaded queue */ -- raw_spin_lock(&rt_rq->push_lock); -- /* -- * If the source queue changed since the IPI went out, -- * we need to restart the search from that CPU again. -- */ -- if (rt_rq->push_flags & RT_PUSH_IPI_RESTART) { -- rt_rq->push_flags &= ~RT_PUSH_IPI_RESTART; -- rt_rq->push_cpu = src_rq->cpu; -- } -+ raw_spin_lock(&rq->rd->rto_lock); - -- cpu = find_next_push_cpu(src_rq); -+ /* Pass the IPI to the next rt overloaded queue */ -+ cpu = rto_next_cpu(rq); - -- if (cpu >= nr_cpu_ids) -- rt_rq->push_flags &= ~RT_PUSH_IPI_EXECUTING; -- raw_spin_unlock(&rt_rq->push_lock); -+ raw_spin_unlock(&rq->rd->rto_lock); - -- if (cpu >= nr_cpu_ids) -+ if (cpu < 0) - return; - -- /* -- * It is possible that a restart caused this CPU to be -- * chosen again. Don't bother with an IPI, just see if we -- * have more to push. -- */ -- if (unlikely(cpu == rq->cpu)) -- goto again; -- - /* Try the next RT overloaded CPU */ -- irq_work_queue_on(&rt_rq->push_work, cpu); --} -- --static void push_irq_work_func(struct irq_work *work) --{ -- struct rt_rq *rt_rq = container_of(work, struct rt_rq, push_work); -- -- try_to_push_tasks(rt_rq); -+ irq_work_queue_on(&rq->rd->rto_push_work, cpu); - } - #endif /* HAVE_RT_PUSH_IPI */ - -diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h -index 55d92a1ca070..448a8266ceea 100644 ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -429,7 +429,7 @@ static inline int rt_bandwidth_enabled(void) - } - - /* RT IPI pull logic requires IRQ_WORK */ --#ifdef CONFIG_IRQ_WORK -+#if defined(CONFIG_IRQ_WORK) && defined(CONFIG_SMP) - # define HAVE_RT_PUSH_IPI - #endif - -@@ -450,12 +450,6 @@ struct rt_rq { - unsigned long rt_nr_total; - int overloaded; - struct plist_head pushable_tasks; --#ifdef HAVE_RT_PUSH_IPI -- int push_flags; -- int push_cpu; -- struct irq_work push_work; -- raw_spinlock_t push_lock; --#endif - #endif /* CONFIG_SMP */ - int rt_queued; - -@@ -537,6 +531,19 @@ struct root_domain { - struct dl_bw dl_bw; - struct cpudl cpudl; - -+#ifdef HAVE_RT_PUSH_IPI -+ /* -+ * For IPI pull requests, loop across the rto_mask. -+ */ -+ struct irq_work rto_push_work; -+ raw_spinlock_t rto_lock; -+ /* These are only updated and read within rto_lock */ -+ int rto_loop; -+ int rto_cpu; -+ /* These atomics are updated outside of a lock */ -+ atomic_t rto_loop_next; -+ atomic_t rto_loop_start; -+#endif - /* - * The "RT overload" flag: it gets set if a CPU has more than - * one runnable RT task. -@@ -547,6 +554,9 @@ struct root_domain { - - extern struct root_domain def_root_domain; - -+#ifdef HAVE_RT_PUSH_IPI -+extern void rto_push_irq_work_func(struct irq_work *work); -+#endif - #endif /* CONFIG_SMP */ - - /* -diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c -index e24388a863a7..468fb7cd1221 100644 ---- a/lib/mpi/mpi-pow.c -+++ b/lib/mpi/mpi-pow.c -@@ -26,6 +26,7 @@ - * however I decided to publish this code under the plain GPL. - */ - -+#include - #include - #include "mpi-internal.h" - #include "longlong.h" -@@ -256,6 +257,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) - } - e <<= 1; - c--; -+ cond_resched(); - } - - i--; -diff --git a/net/9p/client.c b/net/9p/client.c -index f5feac4ff4ec..3ff26eb1ea20 100644 ---- a/net/9p/client.c -+++ b/net/9p/client.c -@@ -749,8 +749,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) - } - again: - /* Wait for the response */ -- err = wait_event_interruptible(*req->wq, -- req->status >= REQ_STATUS_RCVD); -+ err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); - - /* - * Make sure our req is coherent with regard to updates in other -diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c -index 6e70ddb158b4..2ddeecca5b12 100644 ---- a/net/9p/trans_virtio.c -+++ b/net/9p/trans_virtio.c -@@ -290,8 +290,8 @@ req_retry: - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); -- err = wait_event_interruptible(*chan->vc_wq, -- chan->ring_bufs_avail); -+ err = wait_event_killable(*chan->vc_wq, -+ chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - return err; - -@@ -331,7 +331,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, - * Other zc request to finish here - */ - if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { -- err = wait_event_interruptible(vp_wq, -+ err = wait_event_killable(vp_wq, - (atomic_read(&vp_pinned) < chan->p9_max_pages)); - if (err == -ERESTARTSYS) - return err; -@@ -475,8 +475,8 @@ req_retry_pinned: - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); -- err = wait_event_interruptible(*chan->vc_wq, -- chan->ring_bufs_avail); -+ err = wait_event_killable(*chan->vc_wq, -+ chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - goto err_out; - -@@ -493,8 +493,7 @@ req_retry_pinned: - virtqueue_kick(chan->vq); - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); -- err = wait_event_interruptible(*req->wq, -- req->status >= REQ_STATUS_RCVD); -+ err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); - /* - * Non kernel buffers are pinned, unpin them - */ -diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c -index f300d1cbfa91..097a1243c16c 100644 ---- a/net/ipv4/ip_sockglue.c -+++ b/net/ipv4/ip_sockglue.c -@@ -808,6 +808,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, - { - struct ip_mreqn mreq; - struct net_device *dev = NULL; -+ int midx; - - if (sk->sk_type == SOCK_STREAM) - goto e_inval; -@@ -852,11 +853,15 @@ static int do_ip_setsockopt(struct sock *sk, int level, - err = -EADDRNOTAVAIL; - if (!dev) - break; -+ -+ midx = l3mdev_master_ifindex(dev); -+ - dev_put(dev); - - err = -EINVAL; - if (sk->sk_bound_dev_if && -- mreq.imr_ifindex != sk->sk_bound_dev_if) -+ mreq.imr_ifindex != sk->sk_bound_dev_if && -+ (!midx || midx != sk->sk_bound_dev_if)) - break; - - inet->mc_index = mreq.imr_ifindex; -diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c -index 4449ad1f8114..a4a30d2ca66f 100644 ---- a/net/ipv6/ipv6_sockglue.c -+++ b/net/ipv6/ipv6_sockglue.c -@@ -583,16 +583,24 @@ done: - - if (val) { - struct net_device *dev; -+ int midx; - -- if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) -- goto e_inval; -+ rcu_read_lock(); - -- dev = dev_get_by_index(net, val); -+ dev = dev_get_by_index_rcu(net, val); - if (!dev) { -+ rcu_read_unlock(); - retv = -ENODEV; - break; - } -- dev_put(dev); -+ midx = l3mdev_master_ifindex_rcu(dev); -+ -+ rcu_read_unlock(); -+ -+ if (sk->sk_bound_dev_if && -+ sk->sk_bound_dev_if != val && -+ (!midx || midx != sk->sk_bound_dev_if)) -+ goto e_inval; - } - np->mcast_oif = val; - retv = 0; -diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 48917437550e..7336a7311038 100644 ---- a/net/ipv6/route.c -+++ b/net/ipv6/route.c -@@ -3378,7 +3378,11 @@ static int ip6_route_dev_notify(struct notifier_block *this, - net->ipv6.ip6_blk_hole_entry->dst.dev = dev; - net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); - #endif -- } else if (event == NETDEV_UNREGISTER) { -+ } else if (event == NETDEV_UNREGISTER && -+ dev->reg_state != NETREG_UNREGISTERED) { -+ /* NETDEV_UNREGISTER could be fired for multiple times by -+ * netdev_wait_allrefs(). Make sure we only call this once. -+ */ - in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev); - #ifdef CONFIG_IPV6_MULTIPLE_TABLES - in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev); -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 6837a46ca4a2..7b271f3ded6b 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -682,7 +682,6 @@ struct ieee80211_if_mesh { - const struct ieee80211_mesh_sync_ops *sync_ops; - s64 sync_offset_clockdrift_max; - spinlock_t sync_offset_lock; -- bool adjusting_tbtt; - /* mesh power save */ - enum nl80211_mesh_power_mode nonpeer_pm; - int ps_peers_light_sleep; -diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c -index 9063e8e736ad..9e1ded80a992 100644 ---- a/net/mac80211/mesh.c -+++ b/net/mac80211/mesh.c -@@ -295,8 +295,6 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, - /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ - *pos |= ifmsh->ps_peers_deep_sleep ? - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; -- *pos++ |= ifmsh->adjusting_tbtt ? -- IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; - *pos++ = 0x00; - - return 0; -@@ -866,7 +864,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) - ifmsh->mesh_cc_id = 0; /* Disabled */ - /* register sync ops from extensible synchronization framework */ - ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); -- ifmsh->adjusting_tbtt = false; - ifmsh->sync_offset_clockdrift_max = 0; - set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); - ieee80211_mesh_root_setup(ifmsh); -diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c -index bd3d55eb21d4..9f02e54ad2a5 100644 ---- a/net/mac80211/mesh_plink.c -+++ b/net/mac80211/mesh_plink.c -@@ -495,12 +495,14 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr, - - /* Userspace handles station allocation */ - if (sdata->u.mesh.user_mpm || -- sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) -- cfg80211_notify_new_peer_candidate(sdata->dev, addr, -- elems->ie_start, -- elems->total_len, -- GFP_KERNEL); -- else -+ sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) { -+ if (mesh_peer_accepts_plinks(elems) && -+ mesh_plink_availables(sdata)) -+ cfg80211_notify_new_peer_candidate(sdata->dev, addr, -+ elems->ie_start, -+ elems->total_len, -+ GFP_KERNEL); -+ } else - sta = __mesh_sta_info_alloc(sdata, addr); - - return sta; -diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c -index 64bc22ad9496..16ed43fe4841 100644 ---- a/net/mac80211/mesh_sync.c -+++ b/net/mac80211/mesh_sync.c -@@ -119,7 +119,6 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, - */ - - if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { -- clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); - msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", - sta->sta.addr); - goto no_sync; -@@ -168,11 +167,9 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, - struct beacon_data *beacon) - { - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -- u8 cap; - - WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); - WARN_ON(!rcu_read_lock_held()); -- cap = beacon->meshconf->meshconf_cap; - - spin_lock_bh(&ifmsh->sync_offset_lock); - -@@ -186,21 +183,13 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata, - "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", - ifmsh->sync_offset_clockdrift_max); - set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); -- -- ifmsh->adjusting_tbtt = true; - } else { - msync_dbg(sdata, - "TBTT : max clockdrift=%lld; too small to adjust\n", - (long long)ifmsh->sync_offset_clockdrift_max); - ifmsh->sync_offset_clockdrift_max = 0; -- -- ifmsh->adjusting_tbtt = false; - } - spin_unlock_bh(&ifmsh->sync_offset_lock); -- -- beacon->meshconf->meshconf_cap = ifmsh->adjusting_tbtt ? -- IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING | cap : -- ~IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING & cap; - } - - static const struct sync_method sync_methods[] = { -diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c -index 2cb429d34c03..120e9ae04db3 100644 ---- a/net/netfilter/nf_tables_api.c -+++ b/net/netfilter/nf_tables_api.c -@@ -1996,7 +1996,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, - * is called on error from nf_tables_newrule(). - */ - expr = nft_expr_first(rule); -- while (expr->ops && expr != nft_expr_last(rule)) { -+ while (expr != nft_expr_last(rule) && expr->ops) { - nf_tables_expr_destroy(ctx, expr); - expr = nft_expr_next(expr); - } -diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c -index 61d216eb7917..5d189c11d208 100644 ---- a/net/netfilter/nft_queue.c -+++ b/net/netfilter/nft_queue.c -@@ -37,7 +37,7 @@ static void nft_queue_eval(const struct nft_expr *expr, - - if (priv->queues_total > 1) { - if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) { -- int cpu = smp_processor_id(); -+ int cpu = raw_smp_processor_id(); - - queue = priv->queuenum + cpu % priv->queues_total; - } else { -diff --git a/net/nfc/core.c b/net/nfc/core.c -index c5a2c7e733b3..1471e4b0aa2c 100644 ---- a/net/nfc/core.c -+++ b/net/nfc/core.c -@@ -1093,7 +1093,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, - err_free_dev: - kfree(dev); - -- return ERR_PTR(rc); -+ return NULL; - } - EXPORT_SYMBOL(nfc_allocate_device); - -diff --git a/net/rds/send.c b/net/rds/send.c -index 6815f03324d7..1a3c6acdd3f8 100644 ---- a/net/rds/send.c -+++ b/net/rds/send.c -@@ -959,6 +959,11 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, - ret = rds_cmsg_rdma_map(rs, rm, cmsg); - if (!ret) - *allocated_mr = 1; -+ else if (ret == -ENODEV) -+ /* Accommodate the get_mr() case which can fail -+ * if connection isn't established yet. -+ */ -+ ret = -EAGAIN; - break; - case RDS_CMSG_ATOMIC_CSWP: - case RDS_CMSG_ATOMIC_FADD: -@@ -1072,8 +1077,12 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) - - /* Parse any control messages the user may have included. */ - ret = rds_cmsg_send(rs, rm, msg, &allocated_mr); -- if (ret) -+ if (ret) { -+ /* Trigger connection so that its ready for the next retry */ -+ if (ret == -EAGAIN) -+ rds_conn_connect_if_down(conn); - goto out; -+ } - - if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) { - printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n", -diff --git a/net/sctp/socket.c b/net/sctp/socket.c -index 272edd7748a0..7f0f689b8d2b 100644 ---- a/net/sctp/socket.c -+++ b/net/sctp/socket.c -@@ -4453,10 +4453,6 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) - struct socket *sock; - int err = 0; - -- /* Do not peel off from one netns to another one. */ -- if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) -- return -EINVAL; -- - /* Do not peel off from one netns to another one. */ - if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) - return -EINVAL; -diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c -index 9b5bd6d142dc..60324f7c72bd 100644 ---- a/net/vmw_vsock/af_vsock.c -+++ b/net/vmw_vsock/af_vsock.c -@@ -1209,10 +1209,14 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, - - if (signal_pending(current)) { - err = sock_intr_errno(timeout); -- goto out_wait_error; -+ sk->sk_state = SS_UNCONNECTED; -+ sock->state = SS_UNCONNECTED; -+ goto out_wait; - } else if (timeout == 0) { - err = -ETIMEDOUT; -- goto out_wait_error; -+ sk->sk_state = SS_UNCONNECTED; -+ sock->state = SS_UNCONNECTED; -+ goto out_wait; - } - - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); -@@ -1220,20 +1224,17 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, - - if (sk->sk_err) { - err = -sk->sk_err; -- goto out_wait_error; -- } else -+ sk->sk_state = SS_UNCONNECTED; -+ sock->state = SS_UNCONNECTED; -+ } else { - err = 0; -+ } - - out_wait: - finish_wait(sk_sleep(sk), &wait); - out: - release_sock(sk); - return err; -- --out_wait_error: -- sk->sk_state = SS_UNCONNECTED; -- sock->state = SS_UNCONNECTED; -- goto out_wait; - } - - static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) -@@ -1270,18 +1271,20 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) - listener->sk_err == 0) { - release_sock(listener); - timeout = schedule_timeout(timeout); -+ finish_wait(sk_sleep(listener), &wait); - lock_sock(listener); - - if (signal_pending(current)) { - err = sock_intr_errno(timeout); -- goto out_wait; -+ goto out; - } else if (timeout == 0) { - err = -EAGAIN; -- goto out_wait; -+ goto out; - } - - prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); - } -+ finish_wait(sk_sleep(listener), &wait); - - if (listener->sk_err) - err = -listener->sk_err; -@@ -1301,19 +1304,15 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) - */ - if (err) { - vconnected->rejected = true; -- release_sock(connected); -- sock_put(connected); -- goto out_wait; -+ } else { -+ newsock->state = SS_CONNECTED; -+ sock_graft(connected, newsock); - } - -- newsock->state = SS_CONNECTED; -- sock_graft(connected, newsock); - release_sock(connected); - sock_put(connected); - } - --out_wait: -- finish_wait(sk_sleep(listener), &wait); - out: - release_sock(listener); - return err; -@@ -1513,8 +1512,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - long timeout; - int err; - struct vsock_transport_send_notify_data send_data; -- -- DEFINE_WAIT(wait); -+ DEFINE_WAIT_FUNC(wait, woken_wake_function); - - sk = sock->sk; - vsk = vsock_sk(sk); -@@ -1557,11 +1555,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - if (err < 0) - goto out; - -- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); -- - while (total_written < len) { - ssize_t written; - -+ add_wait_queue(sk_sleep(sk), &wait); - while (vsock_stream_has_space(vsk) == 0 && - sk->sk_err == 0 && - !(sk->sk_shutdown & SEND_SHUTDOWN) && -@@ -1570,27 +1567,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - /* Don't wait for non-blocking sockets. */ - if (timeout == 0) { - err = -EAGAIN; -- goto out_wait; -+ remove_wait_queue(sk_sleep(sk), &wait); -+ goto out_err; - } - - err = transport->notify_send_pre_block(vsk, &send_data); -- if (err < 0) -- goto out_wait; -+ if (err < 0) { -+ remove_wait_queue(sk_sleep(sk), &wait); -+ goto out_err; -+ } - - release_sock(sk); -- timeout = schedule_timeout(timeout); -+ timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout); - lock_sock(sk); - if (signal_pending(current)) { - err = sock_intr_errno(timeout); -- goto out_wait; -+ remove_wait_queue(sk_sleep(sk), &wait); -+ goto out_err; - } else if (timeout == 0) { - err = -EAGAIN; -- goto out_wait; -+ remove_wait_queue(sk_sleep(sk), &wait); -+ goto out_err; - } -- -- prepare_to_wait(sk_sleep(sk), &wait, -- TASK_INTERRUPTIBLE); - } -+ remove_wait_queue(sk_sleep(sk), &wait); - - /* These checks occur both as part of and after the loop - * conditional since we need to check before and after -@@ -1598,16 +1598,16 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - */ - if (sk->sk_err) { - err = -sk->sk_err; -- goto out_wait; -+ goto out_err; - } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || - (vsk->peer_shutdown & RCV_SHUTDOWN)) { - err = -EPIPE; -- goto out_wait; -+ goto out_err; - } - - err = transport->notify_send_pre_enqueue(vsk, &send_data); - if (err < 0) -- goto out_wait; -+ goto out_err; - - /* Note that enqueue will only write as many bytes as are free - * in the produce queue, so we don't need to ensure len is -@@ -1620,7 +1620,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - len - total_written); - if (written < 0) { - err = -ENOMEM; -- goto out_wait; -+ goto out_err; - } - - total_written += written; -@@ -1628,14 +1628,13 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, - err = transport->notify_send_post_enqueue( - vsk, written, &send_data); - if (err < 0) -- goto out_wait; -+ goto out_err; - - } - --out_wait: -+out_err: - if (total_written > 0) - err = total_written; -- finish_wait(sk_sleep(sk), &wait); - out: - release_sock(sk); - return err; -@@ -1716,21 +1715,61 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - if (err < 0) - goto out; - -- prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); - - while (1) { -- s64 ready = vsock_stream_has_data(vsk); -+ s64 ready; - -- if (ready < 0) { -- /* Invalid queue pair content. XXX This should be -- * changed to a connection reset in a later change. -- */ -+ prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); -+ ready = vsock_stream_has_data(vsk); - -- err = -ENOMEM; -- goto out_wait; -- } else if (ready > 0) { -+ if (ready == 0) { -+ if (sk->sk_err != 0 || -+ (sk->sk_shutdown & RCV_SHUTDOWN) || -+ (vsk->peer_shutdown & SEND_SHUTDOWN)) { -+ finish_wait(sk_sleep(sk), &wait); -+ break; -+ } -+ /* Don't wait for non-blocking sockets. */ -+ if (timeout == 0) { -+ err = -EAGAIN; -+ finish_wait(sk_sleep(sk), &wait); -+ break; -+ } -+ -+ err = transport->notify_recv_pre_block( -+ vsk, target, &recv_data); -+ if (err < 0) { -+ finish_wait(sk_sleep(sk), &wait); -+ break; -+ } -+ release_sock(sk); -+ timeout = schedule_timeout(timeout); -+ lock_sock(sk); -+ -+ if (signal_pending(current)) { -+ err = sock_intr_errno(timeout); -+ finish_wait(sk_sleep(sk), &wait); -+ break; -+ } else if (timeout == 0) { -+ err = -EAGAIN; -+ finish_wait(sk_sleep(sk), &wait); -+ break; -+ } -+ } else { - ssize_t read; - -+ finish_wait(sk_sleep(sk), &wait); -+ -+ if (ready < 0) { -+ /* Invalid queue pair content. XXX This should -+ * be changed to a connection reset in a later -+ * change. -+ */ -+ -+ err = -ENOMEM; -+ goto out; -+ } -+ - err = transport->notify_recv_pre_dequeue( - vsk, target, &recv_data); - if (err < 0) -@@ -1750,42 +1789,12 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - vsk, target, read, - !(flags & MSG_PEEK), &recv_data); - if (err < 0) -- goto out_wait; -+ goto out; - - if (read >= target || flags & MSG_PEEK) - break; - - target -= read; -- } else { -- if (sk->sk_err != 0 || (sk->sk_shutdown & RCV_SHUTDOWN) -- || (vsk->peer_shutdown & SEND_SHUTDOWN)) { -- break; -- } -- /* Don't wait for non-blocking sockets. */ -- if (timeout == 0) { -- err = -EAGAIN; -- break; -- } -- -- err = transport->notify_recv_pre_block( -- vsk, target, &recv_data); -- if (err < 0) -- break; -- -- release_sock(sk); -- timeout = schedule_timeout(timeout); -- lock_sock(sk); -- -- if (signal_pending(current)) { -- err = sock_intr_errno(timeout); -- break; -- } else if (timeout == 0) { -- err = -EAGAIN; -- break; -- } -- -- prepare_to_wait(sk_sleep(sk), &wait, -- TASK_INTERRUPTIBLE); - } - } - -@@ -1797,8 +1806,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - if (copied > 0) - err = copied; - --out_wait: -- finish_wait(sk_sleep(sk), &wait); - out: - release_sock(sk); - return err; -diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c -index 0aca39762ed0..cd20f91326fe 100644 ---- a/sound/core/pcm_lib.c -+++ b/sound/core/pcm_lib.c -@@ -264,8 +264,10 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream, - runtime->rate); - *audio_tstamp = ns_to_timespec(audio_nsecs); - } -- runtime->status->audio_tstamp = *audio_tstamp; -- runtime->status->tstamp = *curr_tstamp; -+ if (!timespec_equal(&runtime->status->audio_tstamp, audio_tstamp)) { -+ runtime->status->audio_tstamp = *audio_tstamp; -+ runtime->status->tstamp = *curr_tstamp; -+ } - - /* - * re-take a driver timestamp to let apps detect if the reference tstamp -diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c -index 0b4b028e8e98..de9155eed727 100644 ---- a/sound/core/timer_compat.c -+++ b/sound/core/timer_compat.c -@@ -40,11 +40,11 @@ static int snd_timer_user_info_compat(struct file *file, - struct snd_timer *t; - - tu = file->private_data; -- if (snd_BUG_ON(!tu->timeri)) -- return -ENXIO; -+ if (!tu->timeri) -+ return -EBADFD; - t = tu->timeri->timer; -- if (snd_BUG_ON(!t)) -- return -ENXIO; -+ if (!t) -+ return -EBADFD; - memset(&info, 0, sizeof(info)); - info.card = t->card ? t->card->number : -1; - if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) -@@ -73,8 +73,8 @@ static int snd_timer_user_status_compat(struct file *file, - struct snd_timer_status32 status; - - tu = file->private_data; -- if (snd_BUG_ON(!tu->timeri)) -- return -ENXIO; -+ if (!tu->timeri) -+ return -EBADFD; - memset(&status, 0, sizeof(status)); - status.tstamp.tv_sec = tu->tstamp.tv_sec; - status.tstamp.tv_nsec = tu->tstamp.tv_nsec; -diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c -index e6de496bffbe..e2e08fc73b50 100644 ---- a/sound/pci/hda/hda_intel.c -+++ b/sound/pci/hda/hda_intel.c -@@ -2316,6 +2316,9 @@ static const struct pci_device_id azx_ids[] = { - /* AMD Hudson */ - { PCI_DEVICE(0x1022, 0x780d), - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, -+ /* AMD Raven */ -+ { PCI_DEVICE(0x1022, 0x15e3), -+ .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, - /* ATI HDMI */ - { PCI_DEVICE(0x1002, 0x0002), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index af0962307b7f..e5730a7d0480 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -4404,7 +4404,7 @@ static void alc_no_shutup(struct hda_codec *codec) - static void alc_fixup_no_shutup(struct hda_codec *codec, - const struct hda_fixup *fix, int action) - { -- if (action == HDA_FIXUP_ACT_PRE_PROBE) { -+ if (action == HDA_FIXUP_ACT_PROBE) { - struct alc_spec *spec = codec->spec; - spec->shutup = alc_no_shutup; - } -@@ -6254,7 +6254,7 @@ static int patch_alc269(struct hda_codec *codec) - case 0x10ec0703: - spec->codec_variant = ALC269_TYPE_ALC700; - spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */ -- alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */ -+ alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */ - break; - - } -diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c -index 0bb415a28723..f1f990b325ad 100644 ---- a/sound/soc/codecs/wm_adsp.c -+++ b/sound/soc/codecs/wm_adsp.c -@@ -1060,7 +1060,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) - const struct wmfw_region *region; - const struct wm_adsp_region *mem; - const char *region_name; -- char *file, *text; -+ char *file, *text = NULL; - struct wm_adsp_buf *buf; - unsigned int reg; - int regions = 0; -@@ -1221,10 +1221,21 @@ static int wm_adsp_load(struct wm_adsp *dsp) - regions, le32_to_cpu(region->len), offset, - region_name); - -+ if ((pos + le32_to_cpu(region->len) + sizeof(*region)) > -+ firmware->size) { -+ adsp_err(dsp, -+ "%s.%d: %s region len %d bytes exceeds file length %zu\n", -+ file, regions, region_name, -+ le32_to_cpu(region->len), firmware->size); -+ ret = -EINVAL; -+ goto out_fw; -+ } -+ - if (text) { - memcpy(text, region->data, le32_to_cpu(region->len)); - adsp_info(dsp, "%s: %s\n", file, text); - kfree(text); -+ text = NULL; - } - - if (reg) { -@@ -1269,6 +1280,7 @@ out_fw: - regmap_async_complete(regmap); - wm_adsp_buf_free(&buf_list); - release_firmware(firmware); -+ kfree(text); - out: - kfree(file); - -@@ -1730,6 +1742,17 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) - } - - if (reg) { -+ if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) > -+ firmware->size) { -+ adsp_err(dsp, -+ "%s.%d: %s region len %d bytes exceeds file length %zu\n", -+ file, blocks, region_name, -+ le32_to_cpu(blk->len), -+ firmware->size); -+ ret = -EINVAL; -+ goto out_fw; -+ } -+ - buf = wm_adsp_buf_alloc(blk->data, - le32_to_cpu(blk->len), - &buf_list); -diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c -index 362446c36c9e..e00dfbec22c5 100644 ---- a/sound/soc/sh/rcar/core.c -+++ b/sound/soc/sh/rcar/core.c -@@ -1049,10 +1049,8 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, - return -ENOMEM; - - ret = snd_ctl_add(card, kctrl); -- if (ret < 0) { -- snd_ctl_free_one(kctrl); -+ if (ret < 0) - return ret; -- } - - cfg->update = update; - cfg->card = card; -diff --git a/sound/usb/clock.c b/sound/usb/clock.c -index 7ccbcaf6a147..66294eb64501 100644 ---- a/sound/usb/clock.c -+++ b/sound/usb/clock.c -@@ -43,7 +43,7 @@ static struct uac_clock_source_descriptor * - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_SOURCE))) { -- if (cs->bClockID == clock_id) -+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id) - return cs; - } - -@@ -59,8 +59,11 @@ static struct uac_clock_selector_descriptor * - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_SELECTOR))) { -- if (cs->bClockID == clock_id) -+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id) { -+ if (cs->bLength < 5 + cs->bNrInPins) -+ return NULL; - return cs; -+ } - } - - return NULL; -@@ -75,7 +78,7 @@ static struct uac_clock_multiplier_descriptor * - while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra, - ctrl_iface->extralen, - cs, UAC2_CLOCK_MULTIPLIER))) { -- if (cs->bClockID == clock_id) -+ if (cs->bLength >= sizeof(*cs) && cs->bClockID == clock_id) - return cs; - } - -diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c -index a23efc8671d6..1050008d7719 100644 ---- a/sound/usb/mixer.c -+++ b/sound/usb/mixer.c -@@ -1397,6 +1397,12 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, - __u8 *bmaControls; - - if (state->mixer->protocol == UAC_VERSION_1) { -+ if (hdr->bLength < 7) { -+ usb_audio_err(state->chip, -+ "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", -+ unitid); -+ return -EINVAL; -+ } - csize = hdr->bControlSize; - if (!csize) { - usb_audio_dbg(state->chip, -@@ -1414,6 +1420,12 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, - } - } else { - struct uac2_feature_unit_descriptor *ftr = _ftr; -+ if (hdr->bLength < 6) { -+ usb_audio_err(state->chip, -+ "unit %u: invalid UAC_FEATURE_UNIT descriptor\n", -+ unitid); -+ return -EINVAL; -+ } - csize = 4; - channels = (hdr->bLength - 6) / 4 - 1; - bmaControls = ftr->bmaControls; -@@ -2014,7 +2026,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, - const struct usbmix_name_map *map; - char **namelist; - -- if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { -+ if (desc->bLength < 5 || !desc->bNrInPins || -+ desc->bLength < 5 + desc->bNrInPins) { - usb_audio_err(state->chip, - "invalid SELECTOR UNIT descriptor %d\n", unitid); - return -EINVAL;