[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ipfire-scm
Subject:    [IPFire-SCM] [git.ipfire.org] IPFire 3.x development tree branch, master, updated. 1deaaa3ee1578d8a4
From:       git () ipfire ! org (Michael Tremer)
Date:       2010-09-18 20:04:25
Message-ID: 20100918200426.31B0A20885 () argus ! ipfire ! org
[Download RAW message or body]

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "IPFire 3.x development tree".

The branch, master has been updated
       via  1deaaa3ee1578d8a4ea2de38520e900821161b90 (commit)
       via  f0ba76a17fe4b2c111c1080179173db2c4ced436 (commit)
       via  0261d55ccb8a81296465731814e47d81070519c3 (commit)
       via  57199397231f6b394f83ce6961ebd2f77fa18054 (commit)
       via  2bbc1a853948f6bfb72d8832a29c3f4e389f7770 (commit)
       via  4720b2479af530ee7c8073f384d4ac09623cd7c1 (commit)
       via  18e85acea02d3f8bbfbe06c3bfa0aa836a39105d (commit)
       via  b78bff09d6facd9031078bdac88cfed1fe089a9d (commit)
       via  9b86cf3c211a2330f0fcdea36f6c86d9cde49f76 (commit)
       via  d4f374393f3f2428dc5a7e3d5581863eac086f02 (commit)
       via  bee0d3254fa38e9fd2744e5388bab8d7bb54671e (commit)
       via  a2a7b5a53aefb7f0d220e16d7e9b0b1b2440ea9b (commit)
       via  eabf512342fbd22ca566d6a3179fdcda437ef642 (commit)
       via  267c63e17ef52be5cb91b00e0817d3a865f1592b (commit)
       via  b3efa41b3e6d15313cf60475fab8cebd7427caf4 (commit)
       via  069b1c08a01172860089f203c4a46bd6ec752a19 (commit)
       via  fcfc0d1d4d725a8427ad9e0e7d9578ba74f0074a (commit)
      from  efa6b008b64df19fbf425408f15bdd8e068ad8a2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1deaaa3ee1578d8a4ea2de38520e900821161b90
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:58:18 2010 +0200

    dracut: Remove selinux module.

commit f0ba76a17fe4b2c111c1080179173db2c4ced436
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:52:04 2010 +0200

    kernel: Compile in support for loop devices.

commit 0261d55ccb8a81296465731814e47d81070519c3
Merge: 4720b24 5719939
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:49:53 2010 +0200

    Merge branch 'master' of ssh://git.ipfire.org/pub/git/people/ms/ipfire-3.x into \
next

commit 57199397231f6b394f83ce6961ebd2f77fa18054
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:44:13 2010 +0200

    kernel: Update to 2.6.35.4.

commit 2bbc1a853948f6bfb72d8832a29c3f4e389f7770
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:43:39 2010 +0200

    naoki: Fix personality for shell.

commit 4720b2479af530ee7c8073f384d4ac09623cd7c1
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 21:39:13 2010 +0200

    naoki: Allow replacing of packages with never versions.

commit 18e85acea02d3f8bbfbe06c3bfa0aa836a39105d
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 20:03:24 2010 +0200

    naoki: Do not use host system's PS1 in chroot.
    
    This could contain commands that are not available in
    chroot.

commit b78bff09d6facd9031078bdac88cfed1fe089a9d
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 20:03:06 2010 +0200

    naoki: Make comfortable package shell.

commit 9b86cf3c211a2330f0fcdea36f6c86d9cde49f76
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 16:08:38 2010 +0200

    dracut: Add iputils as a dependency (required for arping).

commit d4f374393f3f2428dc5a7e3d5581863eac086f02
Merge: fcfc0d1 bee0d32
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 16:08:04 2010 +0200

    Merge branch 'master' of ssh://git.ipfire.org/pub/git/people/ms/ipfire-3.x into \
next

commit bee0d3254fa38e9fd2744e5388bab8d7bb54671e
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 15:06:14 2010 +0200

    naoki: Fix import of exceptions in packages.py.
    
    DownloadError was undefined.

commit a2a7b5a53aefb7f0d220e16d7e9b0b1b2440ea9b
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 15:03:03 2010 +0200

    naoki: Oops. Left a print command for debugging.

commit eabf512342fbd22ca566d6a3179fdcda437ef642
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 15:00:44 2010 +0200

    naoki: Remove unused command line arguments.

commit 267c63e17ef52be5cb91b00e0817d3a865f1592b
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 14:59:20 2010 +0200

    naoki: Add command line command to find provides.

commit b3efa41b3e6d15313cf60475fab8cebd7427caf4
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 14:58:51 2010 +0200

    noaki: Make search for provides find all kinds of dependencies.

commit 069b1c08a01172860089f203c4a46bd6ec752a19
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 14:33:43 2010 +0200

    naoki: Replace dependency resolution by a more dynamic way.
    
    Improved some parts of the dependency resolution with allows to
    replace packages and is more efficient.

commit fcfc0d1d4d725a8427ad9e0e7d9578ba74f0074a
Author: Michael Tremer <michael.tremer at ipfire.org>
Date:   Sat Sep 18 12:49:27 2010 +0200

    Revert "kernel: Create initrd in the build system."
    
    This reverts commit 68886c54dad5bba98544ddc98910121fe94a9038.

-----------------------------------------------------------------------

Summary of changes:
 naoki/__init__.py                                  |   11 +
 naoki/build.py                                     |   36 +-
 naoki/constants.py                                 |    4 +-
 naoki/dependencies.py                              |  102 +-
 naoki/environ.py                                   |    9 +-
 naoki/packages.py                                  |   18 +
 naoki/repositories.py                              |   19 +-
 naoki/terminal.py                                  |   11 +-
 pkgs/core/dracut/dracut.nm                         |    8 +-
 pkgs/core/kernel/config                            |  233 +-
 pkgs/core/kernel/kernel.nm                         |   10 +-
 pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch    |26270 --------------------
 ...> grsecurity-2.2.0-2.6.35.4-201009172030.patch} |19800 ++++++++-------
 ...routes-2.6.34-16.diff => routes-2.6.35-16.diff} |  226 +-
 14 files changed, 11385 insertions(+), 35372 deletions(-)
 delete mode 100644 pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch
 rename pkgs/core/kernel/patches/{grsecurity-2.2.0-2.6.34.1-201007070910.patch => \
grsecurity-2.2.0-2.6.35.4-201009172030.patch} (79%)  rename \
pkgs/core/kernel/patches/{routes-2.6.34-16.diff => routes-2.6.35-16.diff} (83%)

Difference in files:
diff --git a/naoki/__init__.py b/naoki/__init__.py
index 166abbf..f8719df 100644
--- a/naoki/__init__.py
+++ b/naoki/__init__.py
@@ -9,6 +9,7 @@ import time
 
 import architectures
 import build
+import dependencies
 import environ
 import generators
 import logger
@@ -93,6 +94,7 @@ class Naoki(object):
 			"list" : self.call_package_list,
 			"groups" : self.call_package_groups,
 			"raw"  : self.call_package_raw,
+			"provides" : self.call_package_provides,
 		}
 
 		return actionmap[args.action.name](args.action)
@@ -179,6 +181,15 @@ Release       : %(PKG_REL)s
 
 		p.print_raw_info()
 
+	def call_package_provides(self, args):
+		provides = dependencies.Provides(args.provides)
+
+		arch = architectures.Architectures().get_default()
+		repo = repositories.BinaryRepository(arch)
+
+		for package in repo.find_packages_by_provides(provides):
+			print package.fmtstr("%(PKG_NAME)s	%(PKG_VER)s-%(PKG_REL)s	%(PKG_SUMMARY)s")
+
 	def call_source(self, args):
 		if not args.has_key("action"):
 			self.cli.help()
diff --git a/naoki/build.py b/naoki/build.py
index 9bc7d92..259d6a0 100644
--- a/naoki/build.py
+++ b/naoki/build.py
@@ -105,5 +105,37 @@ class Jobs(object):
 			self.__jobs.remove(job)
 
 
-class PackageShell(environ.Shell):
-	pass
+class PackageShell(Build):
+	def __init__(self, *args, **kwargs):
+		Build.__init__(self, *args, **kwargs)
+
+		# Add shell packages to have a little bit more
+		# comfort in here...
+		for dependency in config["shell_packages"]:
+			dependency = dependencies.Dependency(dependency)
+			self.dependency_set.add_dependency(dependency)
+
+	def shell(self, **settings):
+		# Resolve the dependencies
+		try:
+			self.dependency_set.resolve()
+		except DependencyResolutionError, e:
+			if self.settings["ignore_dependency_errors"]:
+				logging.warning("Ignoring dependency errors: %s" % e)
+			else:
+				raise
+
+		e = environ.Build(self.package, build_id="%s" % self.id)
+
+		# Extract all tools
+		for package in self.dependency_set.packages:
+			e.extract(package)
+
+		# Download the source tarballs
+		self.package.source_download()
+
+		# Preparing source...
+		e.make("prepare")
+
+		# Run the shell
+		e.shell()
diff --git a/naoki/constants.py b/naoki/constants.py
index 861c83c..8316194 100644
--- a/naoki/constants.py
+++ b/naoki/constants.py
@@ -30,6 +30,8 @@ LOCK_BATCH = os.path.join(BUILDDIR, ".batch")
 
 LOG_MARKER = "### LOG MARKER ###"
 
+DEP_INVALID, DEP_FILE, DEP_LIBRARY, DEP_PACKAGE = range(4)
+
 def calc_parallelism():
 	"""
 		Calculate how many processes to run
@@ -140,7 +142,7 @@ class Config(object):
 		ret = {
 			"HOME"           : os.environ.get("HOME", "/root"),
 			"TERM"           : os.environ.get("TERM", ""),
-			"PS1"            : os.environ.get("PS1", "\u:\w\$ "),
+			"PS1"            : "\u:\w\$ ",
 			#
 			"DISTRO_NAME"    : self["distro_name"],
 			"DISTRO_SNAME"   : self["distro_sname"],
diff --git a/naoki/dependencies.py b/naoki/dependencies.py
index f5dd46b..9578aaa 100644
--- a/naoki/dependencies.py
+++ b/naoki/dependencies.py
@@ -8,19 +8,14 @@ import architectures
 import repositories
 import packages
 
+from constants import *
 from exception import *
 
-DEP_INVALID, DEP_FILE, DEP_LIBRARY, DEP_PACKAGE = range(4)
-
-
 class Dependency(object):
 	def __init__(self, identifier, origin=None):
 		self.identifier = identifier
 		self.origin = origin
 
-	def __cmp__(self, other):
-		return cmp(self.identifier, other.identifier)
-
 	def __repr__(self):
 		s = "<%s %s" % (self.__class__.__name__, self.identifier)
 		if self.origin:
@@ -44,6 +39,8 @@ class Dependency(object):
 		return self.type == other.type \
 			and self.identifier == other.identifier
 
+	__eq__ = match
+
 
 class Provides(Dependency):
 	pass
@@ -61,7 +58,6 @@ class DependencySet(object):
 		# initialize package lists
 		self._dependencies = []
 		self._items = []
-		self._provides = []
 
 		# add all provided dependencies
 		for dependency in dependencies:
@@ -94,41 +90,29 @@ class DependencySet(object):
 			return
 
 		# Packages conflict
-		if item.name in [i.name for i in self._items]:
-			logging.debug("Cannot add package with same name but different version: %s" % \
                item)
-			return
-
-		for provides in item.get_provides():
-			self.add_provides(provides)
-
-		for dependency in item.get_dependencies():
-			self.add_dependency(dependency)
+		for package in self._items:
+			if package.name == item.name:
+				if item > package:
+					logging.update("Replacing package %s by %s" % (package, item))
+					self._items.remove(package)
+					break
 
 		self._items.append(item)
 		logging.debug("Added new package %s" % item)
 
-	def add_provides(self, item):
-		assert isinstance(item, Provides)
-
-		if item in self._provides:
-			return
-
-		self._provides.append(item)
-		self._provides.sort()
-
 	def resolve(self):
 		logging.debug("Resolving %s" % self)
 
 		# Safe for endless loop
 		counter = 1000
 
-		while self._dependencies:
+		while self.unresolved_dependencies:
 			counter -= 1
 			if not counter:
 				logging.debug("Maximum count of dependency loop was reached")
 				break
 
-			dependency = self._dependencies.pop(0)
+			dependency = self.unresolved_dependencies.pop(0)
 
 			logging.debug("Processing dependency: %s" % dependency.identifier)
 
@@ -140,11 +124,10 @@ class DependencySet(object):
 					continue
 
 			elif dependency.type == DEP_LIBRARY:
-				for package in self.repo.all:
-					for provides in package.get_provides():
-						if provides.match(dependency):
-							self.add_package(package)
-							break
+				package = self.repo.find_package_by_provides(dependency)
+				if package:
+					self.add_package(package)
+					continue
 
 			elif dependency.type == DEP_FILE:
 				package = self.repo.find_package_by_file(dependency.identifier)
@@ -159,32 +142,63 @@ class DependencySet(object):
 				logging.warning("Dropping invalid dependency %s" % dependency.identifier)
 				continue
 
-			# Found not solution, push it to the end
+			# Found not solution
 			logging.debug("No match found: %s" % dependency)
-			self.add_dependency(dependency)
 
-		if self.dependencies:
+		if self.unresolved_dependencies:
 			#logging.error("Unresolveable dependencies: %s" % self.dependencies)
-			raise DependencyResolutionError, "%s" % self.dependencies
+			raise DependencyResolutionError, "%s" % self.unresolved_dependencies
 
 	@property
-	def dependencies(self):
-		return sorted(self._dependencies)
+	def unresolved_dependencies(self):
+		dependencies = []
+
+		# XXX These are not so nice because they possibly check all packages
+		# and do not break after the first match
+		for dependency in self._dependencies + self.dependencies:
+			if dependency.type == DEP_INVALID:
+				continue
+
+			found = False
+			for item in self._items:
+				if item.does_provide(dependency):
+					found = True
+					break
+
+			if found:
+				continue
+
+			for provide in self.provides:
+				if dependency.match(provide):
+					found = True
+					break
+
+			if found:
+				continue
+
+			dependencies.append(dependency)
+
+		return dependencies
 
 	@property
-	def items(self):
-		#if not self._items:
-		#	self.resolve()
+	def dependencies(self):
+		dependencies = []
+		for item in self._items:
+			dependencies += item.get_dependencies()
 
-		return self._items
+		return list(set(dependencies))
 
 	@property
 	def packages(self):
-		return sorted(self.items)
+		return sorted(self._items)
 
 	@property
 	def provides(self):
-		return self._provides
+		provides = []
+		for item in self._items:
+			provides += item.get_provides()
+
+		return list(set(provides))
 
 
 if __name__ == "__main__":
diff --git a/naoki/environ.py b/naoki/environ.py
index ee5fc62..4987eac 100644
--- a/naoki/environ.py
+++ b/naoki/environ.py
@@ -315,14 +315,9 @@ class Build(_Environment):
 		return self.doChroot("make -C %s -f %s %s" % \
 			(os.path.dirname(file), file, target), shell=True)
 
-
-class Shell(Build):
 	def shell(self, args=[]):
-		# Preparing source...
-		self.make("prepare")
-
-		command = "chroot %s /usr/src/tools/chroot-shell %s" % \
-			(self.chrootPath(), " ".join(args))
+		command = "%s chroot %s /usr/src/tools/chroot-shell %s" % \
+			(self.arch.personality, self.chrootPath(), " ".join(args))
 
 		for key, val in self.variables().items():
 			command = "%s=\"%s\" " % (key, val) + command
diff --git a/naoki/packages.py b/naoki/packages.py
index e726607..5c8e137 100644
--- a/naoki/packages.py
+++ b/naoki/packages.py
@@ -14,6 +14,7 @@ import io
 import util
 
 from constants import *
+from exception import *
 
 def version_compare_epoch(e1, e2):
 	return cmp(e1, e2)
@@ -286,3 +287,20 @@ class BinaryPackage(Package):
 				self._filelist.append(file)
 
 		return self._filelist
+
+	def does_provide(self, what):
+		if what.type == DEP_PACKAGE:
+			return what.identifier == self.name
+
+		elif what.type == DEP_FILE:
+			return what.identifier in self.filelist
+
+		elif what.type in (DEP_LIBRARY,):
+			for provide in self.get_provides():
+				if provide.match(what):
+					return True
+
+			return False
+
+		# For invalid dependencies alsways return false
+		return False
diff --git a/naoki/repositories.py b/naoki/repositories.py
index 709c669..3eacc0f 100644
--- a/naoki/repositories.py
+++ b/naoki/repositories.py
@@ -45,7 +45,7 @@ class BinaryRepository(Repository):
 			if package.name == name:
 				pkgs.append(package)
 
-		return sorted(pkgs, key=operator.attrgetter("release"), reverse=True)
+		return sorted(pkgs, reverse=True)
 
 	@property
 	def all(self):
@@ -79,7 +79,22 @@ class BinaryRepository(Repository):
 			if filename in package.filelist:
 				pkgs.append(package)
 
-		return sorted(pkgs, key=operator.attrgetter("release"), reverse=True)
+		return sorted(pkgs, reverse=True)
+
+	def find_package_by_provides(self, provides):
+		pkgs = self.find_packages_by_provides(provides)
+
+		if pkgs:
+			return pkgs[0]
+
+	def find_packages_by_provides(self, provides):
+		pkgs = []
+
+		for package in self.all:
+			if package.does_provide(provides):
+				pkgs.append(package)
+
+		return sorted(pkgs, reverse=True)
 
 
 class SourceRepository(Repository):
diff --git a/naoki/terminal.py b/naoki/terminal.py
index 8e9d71d..43caa74 100644
--- a/naoki/terminal.py
+++ b/naoki/terminal.py
@@ -283,12 +283,9 @@ class Commandline(object):
 					help="Primary build command",
 					arguments=[
 						Option("all", ["--all"], help="Build all packages"),
-						Option("withdeps", ["--with-deps"], help="Build all dependencies first if \
                needed"),
-						Option("onlydeps", ["--only-deps"], help="Build only dependencies that belong \
                to a package"),
-						Option("shell", ["-s", "--shell"], help="Change into a chroot environment"),
 						Option("ignore_dependency_errors", ["-i", "--ignore-dependency-errors"],
 							help="Ignore dependency errors."),
-						List("packages", help="Give a list of packages to build or say 'all'"),
+						List("packages", help="Give a list of packages to build."),
 					]),
 
 				# Package
@@ -301,7 +298,6 @@ class Commandline(object):
 								Option("machine", ["--machine"], help="Output in machine parseable format"),
 								List("packages"),
 							]),
-						Parser("tree", help="Show package tree"),
 						Parser("list",
 							help="Show package list",
 							arguments=[
@@ -317,6 +313,11 @@ class Commandline(object):
 							arguments=[
 								Argument("package", help="Name of the package."),
 							]),
+						Parser("provides",
+							help="Find packages which provide a specific thing.",
+							arguments=[
+								Argument("provides", help="Pattern to search for."),
+							]),
 					]),
 
 				# Source
diff --git a/pkgs/core/dracut/dracut.nm b/pkgs/core/dracut/dracut.nm
index 704e423..ff17f89 100644
--- a/pkgs/core/dracut/dracut.nm
+++ b/pkgs/core/dracut/dracut.nm
@@ -34,8 +34,9 @@ PKG_URL        = http://sourceforge.net/apps/trac/dracut/wiki
 PKG_LICENSE    = GPLv2+
 PKG_SUMMARY    = Initramfs generator using udev.
 
-PKG_DEPS      += bash bzip2 cpio coreutils dmraid e2fsprogs gzip iproute2 kbd \
-	less lvm2 mdadm multipath-tools sysvinit udev util-linux-ng which
+PKG_DEPS      += bash bzip2 cpio coreutils dmraid e2fsprogs gzip iproute2 \
+	iputils kbd less lvm2 mdadm multipath-tools sysvinit udev \
+	util-linux-ng which
 
 define PKG_DESCRIPTION
 	dracut is a new, event-driven initramfs infrastructure based around udev.
@@ -61,4 +62,7 @@ endef
 define STAGE_INSTALL
 	cd $(DIR_APP) && make install DESTDIR=$(BUILDROOT) WITH_SWITCH_ROOT=1 \
 		sbindir=/sbin sysconfdir=/etc mandir=/usr/share/man
+
+	# Remove unneeded modules
+	rm -rfv $(BUILDROOT)/usr/share/dracut/modules.d/*selinux
 endef
diff --git a/pkgs/core/kernel/config b/pkgs/core/kernel/config
index 1ffdbae..e3bbd99 100644
--- a/pkgs/core/kernel/config
+++ b/pkgs/core/kernel/config
@@ -1,12 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.34.1
-# Thu Aug 26 09:14:53 2010
+# Linux kernel version: 2.6.35.4
+# Sat Sep 18 18:55:00 2010
 #
 # CONFIG_64BIT is not set
 CONFIG_X86_32=y
 # CONFIG_X86_64 is not set
 CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
 CONFIG_OUTPUT_FORMAT="elf32-i386"
 CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
 CONFIG_GENERIC_TIME=y
@@ -20,6 +21,7 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_MMU=y
 CONFIG_ZONE_DMA=y
 CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_GENERIC_BUG=y
@@ -55,6 +57,7 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_X86_32_SMP=y
 CONFIG_X86_HT=y
 CONFIG_X86_TRAMPOLINE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
 CONFIG_KTIME_SCALAR=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 CONFIG_CONSTRUCTORS=y
@@ -65,6 +68,7 @@ CONFIG_CONSTRUCTORS=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_HAVE_KERNEL_GZIP=y
@@ -82,7 +86,9 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
 
 #
 # RCU Subsystem
@@ -103,18 +109,18 @@ CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
-# CONFIG_NET_NS is not set
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_RD_GZIP=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
 CONFIG_RD_LZO=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
@@ -165,6 +171,7 @@ CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
 CONFIG_HAVE_DMA_API_DEBUG=y
 CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
 CONFIG_HAVE_USER_RETURN_NOTIFIER=y
 
 #
@@ -304,7 +311,6 @@ CONFIG_CPU_SUP_AMD=y
 CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_CPU_SUP_TRANSMETA_32=y
 CONFIG_CPU_SUP_UMC_32=y
-# CONFIG_X86_DS is not set
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
 CONFIG_DMI=y
@@ -355,6 +361,8 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_SPARSEMEM_STATIC=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
@@ -416,6 +424,10 @@ CONFIG_ACPI_PCI_SLOT=y
 CONFIG_X86_PM_TIMER=y
 # CONFIG_ACPI_CONTAINER is not set
 # CONFIG_ACPI_SBS is not set
+CONFIG_ACPI_HED=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=m
+CONFIG_ACPI_APEI_EINJ=m
 # CONFIG_SFI is not set
 
 #
@@ -465,6 +477,7 @@ CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y
 CONFIG_CPU_IDLE=y
 CONFIG_CPU_IDLE_GOV_LADDER=y
 CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_INTEL_IDLE=m
 
 #
 # Bus options (PCI etc.)
@@ -480,6 +493,7 @@ CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCI_OLPC=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_CNB20LE_QUIRK=y
 CONFIG_DMAR=y
 CONFIG_DMAR_DEFAULT_ON=y
 CONFIG_DMAR_FLOPPY_WA=y
@@ -517,7 +531,7 @@ CONFIG_YENTA_ENE_TUNE=y
 CONFIG_YENTA_TOSHIBA=y
 CONFIG_PD6729=m
 CONFIG_I82092=m
-CONFIG_PCCARD_NONSTATIC=m
+CONFIG_PCCARD_NONSTATIC=y
 # CONFIG_HOTPLUG_PCI is not set
 
 #
@@ -561,6 +575,7 @@ CONFIG_NET_IPIP=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPGRE_BROADCAST=y
 CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
 CONFIG_IP_PIMSM_V1=y
 CONFIG_IP_PIMSM_V2=y
 CONFIG_ARPD=y
@@ -602,6 +617,7 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
 CONFIG_IPV6_PIMSM_V2=y
 # CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
@@ -637,6 +653,16 @@ CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
 CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_CT=m
@@ -648,10 +674,15 @@ CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
 CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
@@ -670,6 +701,7 @@ CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
 CONFIG_NETFILTER_XT_MATCH_OWNER=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
@@ -678,7 +710,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
 CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
@@ -687,7 +718,6 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
-CONFIG_NETFILTER_XT_MATCH_OSF=m
 # CONFIG_IP_VS is not set
 
 #
@@ -786,6 +816,11 @@ CONFIG_ATM_CLIP=m
 # CONFIG_ATM_LANE is not set
 CONFIG_ATM_BR2684=m
 CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
 CONFIG_STP=m
 CONFIG_GARP=m
 CONFIG_BRIDGE=m
@@ -868,6 +903,7 @@ CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_CLS_IND=y
 CONFIG_NET_SCH_FIFO=y
 CONFIG_DCB=y
+CONFIG_RPS=y
 
 #
 # Network testing
@@ -915,6 +951,7 @@ CONFIG_RFKILL=m
 CONFIG_RFKILL_LEDS=y
 CONFIG_RFKILL_INPUT=y
 # CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
 
 #
 # Device Drivers
@@ -959,7 +996,7 @@ CONFIG_BLK_CPQ_CISS_DA=m
 CONFIG_BLK_DEV_DAC960=m
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 # CONFIG_BLK_DEV_DRBD is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -1150,30 +1187,46 @@ CONFIG_ATA=m
 CONFIG_ATA_VERBOSE_ERROR=y
 CONFIG_ATA_ACPI=y
 CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
 CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_SATA_INIC162X=m
 CONFIG_SATA_SIL24=m
 CONFIG_ATA_SFF=y
-CONFIG_SATA_SVW=m
+
+#
+# SFF controllers with custom DMA interface
+#
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
 CONFIG_ATA_PIIX=m
 CONFIG_SATA_MV=m
 CONFIG_SATA_NV=m
-CONFIG_PDC_ADMA=m
-CONFIG_SATA_QSTOR=m
 CONFIG_SATA_PROMISE=m
-CONFIG_SATA_SX4=m
 CONFIG_SATA_SIL=m
 CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
 CONFIG_SATA_ULI=m
 CONFIG_SATA_VIA=m
 CONFIG_SATA_VITESSE=m
-CONFIG_SATA_INIC162X=m
-CONFIG_PATA_ACPI=m
+
+#
+# PATA SFF controllers with BMDMA
+#
 CONFIG_PATA_ALI=m
 CONFIG_PATA_AMD=m
 CONFIG_PATA_ARTOP=m
-CONFIG_PATA_ATP867X=m
 CONFIG_PATA_ATIIXP=m
-CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_ATP867X=m
 CONFIG_PATA_CMD64X=m
 CONFIG_PATA_CS5520=m
 CONFIG_PATA_CS5530=m
@@ -1181,40 +1234,50 @@ CONFIG_PATA_CS5535=m
 CONFIG_PATA_CS5536=m
 CONFIG_PATA_CYPRESS=m
 CONFIG_PATA_EFAR=m
-CONFIG_ATA_GENERIC=m
 CONFIG_PATA_HPT366=m
 CONFIG_PATA_HPT37X=m
 CONFIG_PATA_HPT3X2N=m
 CONFIG_PATA_HPT3X3=m
 CONFIG_PATA_HPT3X3_DMA=y
-CONFIG_PATA_IT821X=m
 CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
 CONFIG_PATA_JMICRON=m
-CONFIG_PATA_LEGACY=m
-CONFIG_PATA_TRIFLEX=m
 CONFIG_PATA_MARVELL=m
-CONFIG_PATA_MPIIX=m
-CONFIG_PATA_OLDPIIX=m
 CONFIG_PATA_NETCELL=m
 CONFIG_PATA_NINJA32=m
-CONFIG_PATA_NS87410=m
 CONFIG_PATA_NS87415=m
-CONFIG_PATA_OPTI=m
+CONFIG_PATA_OLDPIIX=m
 CONFIG_PATA_OPTIDMA=m
-CONFIG_PATA_PCMCIA=m
 CONFIG_PATA_PDC2027X=m
 CONFIG_PATA_PDC_OLD=m
 CONFIG_PATA_RADISYS=m
 CONFIG_PATA_RDC=m
-CONFIG_PATA_RZ1000=m
 CONFIG_PATA_SC1200=m
+CONFIG_PATA_SCH=m
 CONFIG_PATA_SERVERWORKS=m
 CONFIG_PATA_SIL680=m
 CONFIG_PATA_SIS=m
 CONFIG_PATA_TOSHIBA=m
+CONFIG_PATA_TRIFLEX=m
 CONFIG_PATA_VIA=m
 CONFIG_PATA_WINBOND=m
-CONFIG_PATA_SCH=m
+
+#
+# PIO-only SFF controllers
+#
+CONFIG_PATA_CMD640_PCI=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_OPTI=m
+CONFIG_PATA_PCMCIA=m
+CONFIG_PATA_RZ1000=m
+
+#
+# Generic fallback / legacy drivers
+#
+CONFIG_PATA_ACPI=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_LEGACY=m
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
@@ -1348,7 +1411,6 @@ CONFIG_B44_PCI_AUTOSELECT=y
 CONFIG_B44_PCICORE_AUTOSELECT=y
 CONFIG_B44_PCI=y
 CONFIG_FORCEDETH=m
-CONFIG_FORCEDETH_NAPI=y
 CONFIG_E100=m
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
@@ -1436,6 +1498,7 @@ CONFIG_BE2NET=m
 CONFIG_WLAN=y
 CONFIG_PCMCIA_RAYCS=m
 CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
 CONFIG_LIBERTAS_THINFIRM_USB=m
 CONFIG_AIRO=m
 CONFIG_ATMEL=m
@@ -1461,6 +1524,8 @@ CONFIG_ATH9K_HW=m
 CONFIG_ATH9K_COMMON=m
 CONFIG_ATH9K=m
 # CONFIG_ATH9K_DEBUGFS is not set
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
 CONFIG_AR9170_USB=m
 CONFIG_AR9170_LEDS=y
 CONFIG_B43=m
@@ -1512,6 +1577,7 @@ CONFIG_LIBERTAS_CS=m
 # CONFIG_LIBERTAS_DEBUG is not set
 CONFIG_LIBERTAS_MESH=y
 CONFIG_HERMES=m
+CONFIG_HERMES_PRISM=y
 CONFIG_HERMES_CACHE_FW_ON_INIT=y
 CONFIG_PLX_HERMES=m
 CONFIG_TMD_HERMES=m
@@ -1519,6 +1585,7 @@ CONFIG_NORTEL_HERMES=m
 CONFIG_PCI_HERMES=m
 CONFIG_PCMCIA_HERMES=m
 CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ORINOCO_USB=m
 CONFIG_P54_COMMON=m
 CONFIG_P54_USB=m
 CONFIG_P54_PCI=m
@@ -1789,9 +1856,10 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ADP5588=m
 CONFIG_KEYBOARD_ATKBD=y
-CONFIG_QT2160=m
+CONFIG_KEYBOARD_QT2160=m
 # CONFIG_KEYBOARD_LKKBD is not set
 CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_TCA6416=m
 CONFIG_KEYBOARD_MATRIX=m
 CONFIG_KEYBOARD_LM8323=m
 CONFIG_KEYBOARD_MAX7359=m
@@ -1846,6 +1914,7 @@ CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_N_GSM=m
 CONFIG_NOZOMI=m
 
 #
@@ -1869,6 +1938,8 @@ CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_SERIAL_TIMBERDALE=m
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 CONFIG_LEGACY_PTYS=y
@@ -1915,6 +1986,7 @@ CONFIG_HPET_MMAP=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_TELCLOCK is not set
 CONFIG_DEVPORT=y
+# CONFIG_RAMOOPS is not set
 CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
 # CONFIG_I2C_COMPAT is not set
@@ -1958,6 +2030,7 @@ CONFIG_I2C_SCMI=m
 #
 CONFIG_I2C_GPIO=m
 CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
 CONFIG_I2C_SIMTEC=m
 CONFIG_I2C_XILINX=m
 
@@ -1972,7 +2045,6 @@ CONFIG_I2C_TINY_USB=m
 #
 # Other I2C/SMBus bus drivers
 #
-CONFIG_I2C_PCA_PLATFORM=m
 CONFIG_I2C_STUB=m
 CONFIG_SCx200_ACB=m
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -2002,7 +2074,6 @@ CONFIG_GPIO_MAX7300=m
 CONFIG_GPIO_MAX732X=m
 CONFIG_GPIO_PCA953X=m
 CONFIG_GPIO_PCF857X=m
-CONFIG_GPIO_WM8994=m
 CONFIG_GPIO_ADP5588=m
 
 #
@@ -2011,6 +2082,7 @@ CONFIG_GPIO_ADP5588=m
 CONFIG_GPIO_CS5535=m
 CONFIG_GPIO_LANGWELL=y
 CONFIG_GPIO_TIMBERDALE=y
+CONFIG_GPIO_RDC321X=m
 
 #
 # SPI GPIO expanders:
@@ -2019,6 +2091,11 @@ CONFIG_GPIO_TIMBERDALE=y
 #
 # AC97 GPIO expanders:
 #
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_GPIO_JANZ_TTL=m
 CONFIG_W1=m
 CONFIG_W1_CON=y
 
@@ -2043,6 +2120,7 @@ CONFIG_W1_SLAVE_BQ27000=m
 CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 # CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
 CONFIG_BATTERY_DS2760=m
 CONFIG_BATTERY_DS2782=m
 CONFIG_BATTERY_OLPC=m
@@ -2111,12 +2189,14 @@ CONFIG_SENSORS_PCF8591=m
 CONFIG_SENSORS_SHT15=m
 CONFIG_SENSORS_SIS5595=m
 CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
 CONFIG_SENSORS_SMSC47M1=m
 CONFIG_SENSORS_SMSC47M192=m
 CONFIG_SENSORS_SMSC47B397=m
 CONFIG_SENSORS_ADS7828=m
 CONFIG_SENSORS_AMC6821=m
 CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
 CONFIG_SENSORS_TMP401=m
 CONFIG_SENSORS_TMP421=m
 CONFIG_SENSORS_VIA_CPUTEMP=m
@@ -2207,23 +2287,23 @@ CONFIG_SSB_PCMCIAHOST=y
 # CONFIG_SSB_DEBUG is not set
 CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
 CONFIG_SSB_DRIVER_PCICORE=y
-
-#
-# Multifunction device drivers
-#
+CONFIG_MFD_SUPPORT=y
 CONFIG_MFD_CORE=m
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_UCB1400_CORE is not set
 CONFIG_TPS65010=m
+CONFIG_TPS6507X=m
 # CONFIG_MFD_TMIO is not set
 CONFIG_MFD_WM8400=m
-CONFIG_MFD_WM8994=m
 CONFIG_MFD_PCF50633=m
 CONFIG_PCF50633_ADC=m
 CONFIG_PCF50633_GPIO=m
+CONFIG_ABX500_CORE=y
 CONFIG_MFD_TIMBERDALE=m
 CONFIG_LPC_SCH=m
+CONFIG_MFD_RDC321X=m
+CONFIG_MFD_JANZ_CMODIO=m
 CONFIG_REGULATOR=y
 # CONFIG_REGULATOR_DEBUG is not set
 CONFIG_REGULATOR_DUMMY=y
@@ -2235,7 +2315,6 @@ CONFIG_REGULATOR_MAX1586=m
 CONFIG_REGULATOR_MAX8649=m
 CONFIG_REGULATOR_MAX8660=m
 CONFIG_REGULATOR_WM8400=m
-CONFIG_REGULATOR_WM8994=m
 CONFIG_REGULATOR_PCF50633=m
 CONFIG_REGULATOR_LP3971=m
 CONFIG_REGULATOR_TPS65023=m
@@ -2259,6 +2338,13 @@ CONFIG_VIDEO_SAA7146=m
 CONFIG_VIDEO_SAA7146_VV=m
 CONFIG_IR_CORE=m
 CONFIG_VIDEO_IR=m
+CONFIG_RC_MAP=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_IMON=m
 CONFIG_MEDIA_ATTACH=y
 CONFIG_MEDIA_TUNER=m
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -2323,9 +2409,11 @@ CONFIG_VIDEO_ADV7170=m
 CONFIG_VIDEO_ADV7175=m
 CONFIG_VIDEO_UPD64031A=m
 CONFIG_VIDEO_UPD64083=m
-CONFIG_VIDEO_VIVI=m
 CONFIG_VIDEO_BT848=m
 CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
 CONFIG_VIDEO_SAA5246A=m
 CONFIG_VIDEO_SAA5249=m
 CONFIG_VIDEO_ZORAN=m
@@ -2336,6 +2424,7 @@ CONFIG_VIDEO_ZORAN_DC10=m
 CONFIG_VIDEO_ZORAN_LML33=m
 CONFIG_VIDEO_ZORAN_LML33R10=m
 CONFIG_VIDEO_ZORAN_AVS6EYES=m
+CONFIG_VIDEO_MEYE=m
 CONFIG_VIDEO_SAA7134=m
 CONFIG_VIDEO_SAA7134_ALSA=m
 CONFIG_VIDEO_SAA7134_DVB=m
@@ -2390,7 +2479,6 @@ CONFIG_USB_GSPCA_PAC7302=m
 CONFIG_USB_GSPCA_PAC7311=m
 CONFIG_USB_GSPCA_SN9C2028=m
 CONFIG_USB_GSPCA_SN9C20X=m
-CONFIG_USB_GSPCA_SN9C20X_EVDEV=y
 CONFIG_USB_GSPCA_SONIXB=m
 CONFIG_USB_GSPCA_SONIXJ=m
 CONFIG_USB_GSPCA_SPCA500=m
@@ -2419,10 +2507,11 @@ CONFIG_VIDEO_CX231XX_DVB=m
 # CONFIG_USB_ET61X251 is not set
 # CONFIG_USB_SN9C102 is not set
 # CONFIG_USB_ZC0301 is not set
-CONFIG_USB_PWC_INPUT_EVDEV=y
 # CONFIG_USB_ZR364XX is not set
 # CONFIG_USB_STKWEBCAM is not set
 CONFIG_USB_S2255=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
 CONFIG_RADIO_ADAPTERS=y
 # CONFIG_RADIO_GEMTEK_PCI is not set
 # CONFIG_RADIO_MAXIRADIO is not set
@@ -2602,9 +2691,11 @@ CONFIG_DVB_S5H1411=m
 CONFIG_DVB_DIB8000=m
 CONFIG_DVB_PLL=m
 CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
 CONFIG_DVB_LNBP21=m
 CONFIG_DVB_ISL6405=m
 CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
 CONFIG_DVB_LGS8GXX=m
 CONFIG_DVB_ATBM8830=m
 CONFIG_DAB=y
@@ -2709,6 +2800,7 @@ CONFIG_FB_SIS=m
 CONFIG_FB_SIS_300=y
 CONFIG_FB_SIS_315=y
 CONFIG_FB_VIA=m
+# CONFIG_FB_VIA_DIRECT_PROCFS is not set
 CONFIG_FB_NEOMAGIC=m
 CONFIG_FB_KYRO=m
 CONFIG_FB_3DFX=m
@@ -2735,7 +2827,6 @@ CONFIG_FB_MB862XX_PCI_GDC=y
 CONFIG_FB_BROADSHEET=m
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=m
-# CONFIG_LCD_ILI9320 is not set
 CONFIG_LCD_PLATFORM=m
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_GENERIC=m
@@ -2743,6 +2834,8 @@ CONFIG_BACKLIGHT_GENERIC=m
 # CONFIG_BACKLIGHT_CARILLO_RANCH is not set
 CONFIG_BACKLIGHT_MBP_NVIDIA=m
 CONFIG_BACKLIGHT_SAHARA=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_PCF50633=m
 
 #
 # Display device support
@@ -2818,6 +2911,7 @@ CONFIG_SND_AD1889=m
 CONFIG_SND_ALS300=m
 CONFIG_SND_ALS4000=m
 CONFIG_SND_ALI5451=m
+CONFIG_SND_ASIHPI=m
 CONFIG_SND_ATIIXP=m
 CONFIG_SND_ATIIXP_MODEM=m
 CONFIG_SND_AU8810=m
@@ -2857,6 +2951,7 @@ CONFIG_SND_ENS1370=m
 CONFIG_SND_ENS1371=m
 CONFIG_SND_ES1938=m
 CONFIG_SND_ES1968=m
+CONFIG_SND_ES1968_INPUT=y
 CONFIG_SND_FM801=m
 CONFIG_SND_FM801_TEA575X_BOOL=y
 CONFIG_SND_FM801_TEA575X=m
@@ -2892,6 +2987,7 @@ CONFIG_SND_INTEL8X0M=m
 CONFIG_SND_KORG1212=m
 CONFIG_SND_LX6464ES=m
 CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MAESTRO3_INPUT=y
 CONFIG_SND_MIXART=m
 CONFIG_SND_NM256=m
 CONFIG_SND_PCXHR=m
@@ -2921,6 +3017,7 @@ CONFIG_SND_SOC=m
 CONFIG_SND_SOC_I2C_AND_SPI=m
 CONFIG_SND_SOC_ALL_CODECS=m
 CONFIG_SND_SOC_WM_HUBS=m
+CONFIG_SND_SOC_AD193X=m
 CONFIG_SND_SOC_AD73311=m
 CONFIG_SND_SOC_ADS117X=m
 CONFIG_SND_SOC_AK4535=m
@@ -2961,11 +3058,11 @@ CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_SOC_WM8988=m
 CONFIG_SND_SOC_WM8990=m
 CONFIG_SND_SOC_WM8993=m
-CONFIG_SND_SOC_WM8994=m
 CONFIG_SND_SOC_WM9081=m
 CONFIG_SND_SOC_MAX9877=m
 CONFIG_SND_SOC_TPA6130A2=m
 CONFIG_SND_SOC_WM2000=m
+CONFIG_SND_SOC_WM9090=m
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
@@ -2986,11 +3083,14 @@ CONFIG_HID_3M_PCT=m
 CONFIG_HID_A4TECH=m
 CONFIG_HID_APPLE=m
 CONFIG_HID_BELKIN=m
+CONFIG_HID_CANDO=m
 CONFIG_HID_CHERRY=m
 CONFIG_HID_CHICONY=m
+# CONFIG_HID_PRODIKEYS is not set
 CONFIG_HID_CYPRESS=m
 CONFIG_HID_DRAGONRISE=m
 # CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EGALAX=m
 CONFIG_HID_EZKEY=m
 CONFIG_HID_KYE=m
 CONFIG_HID_GYRATION=m
@@ -3008,7 +3108,14 @@ CONFIG_HID_ORTEK=m
 CONFIG_HID_PANTHERLORD=m
 # CONFIG_PANTHERLORD_FF is not set
 CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
 CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_ROCCAT_KONE=m
 CONFIG_HID_SAMSUNG=m
 CONFIG_HID_SONY=m
 CONFIG_HID_STANTUM=m
@@ -3022,6 +3129,7 @@ CONFIG_HID_THRUSTMASTER=m
 # CONFIG_THRUSTMASTER_FF is not set
 CONFIG_HID_ZEROPLUS=m
 # CONFIG_ZEROPLUS_FF is not set
+CONFIG_HID_ZYDACRON=m
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -3156,6 +3264,7 @@ CONFIG_LEDS_CLASS=m
 #
 # LED drivers
 #
+CONFIG_LEDS_NET5501=m
 CONFIG_LEDS_ALIX2=m
 CONFIG_LEDS_PCA9532=m
 CONFIG_LEDS_GPIO=m
@@ -3177,7 +3286,7 @@ CONFIG_LEDS_TRIGGERS=y
 # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 CONFIG_LEDS_TRIGGER_BACKLIGHT=m
 CONFIG_LEDS_TRIGGER_GPIO=m
-# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 
 #
 # iptables trigger is under Netfilter config (LED target)
@@ -3253,6 +3362,7 @@ CONFIG_DMADEVICES=y
 #
 CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y
 CONFIG_INTEL_IOATDMA=m
+CONFIG_TIMB_DMA=m
 CONFIG_DMA_ENGINE=y
 
 #
@@ -3271,10 +3381,6 @@ CONFIG_UIO=m
 # CONFIG_UIO_SERCOS3 is not set
 CONFIG_UIO_PCI_GENERIC=m
 CONFIG_UIO_NETX=m
-
-#
-# TI VLYNQ
-#
 # CONFIG_STAGING is not set
 CONFIG_X86_PLATFORM_DEVICES=y
 # CONFIG_ACER_WMI is not set
@@ -3427,6 +3533,7 @@ CONFIG_MISC_FILESYSTEMS=y
 CONFIG_LOGFS=m
 # CONFIG_CRAMFS is not set
 CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTRS=y
 # CONFIG_SQUASHFS_EMBEDDED is not set
 CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
 # CONFIG_VXFS_FS is not set
@@ -3438,20 +3545,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_EXOFS_FS is not set
-CONFIG_AUFS_FS=m
-CONFIG_AUFS_BRANCH_MAX_127=y
-# CONFIG_AUFS_BRANCH_MAX_511 is not set
-# CONFIG_AUFS_BRANCH_MAX_1023 is not set
-# CONFIG_AUFS_BRANCH_MAX_32767 is not set
-# CONFIG_AUFS_HNOTIFY is not set
-# CONFIG_AUFS_EXPORT is not set
-# CONFIG_AUFS_RDU is not set
-CONFIG_AUFS_SP_IATTR=y
-# CONFIG_AUFS_SHWH is not set
-# CONFIG_AUFS_BR_RAMFS is not set
-# CONFIG_AUFS_BR_FUSE is not set
-CONFIG_AUFS_BDEV_LOOP=y
-# CONFIG_AUFS_DEBUG is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -3571,6 +3664,7 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_HAVE_ARCH_KMEMCHECK=y
@@ -3717,7 +3811,7 @@ CONFIG_PAX_PAGEEXEC=y
 CONFIG_PAX_SEGMEXEC=y
 CONFIG_PAX_EMUTRAMP=y
 CONFIG_PAX_MPROTECT=y
-CONFIG_PAX_NOELFRELOCS=y
+CONFIG_PAX_ELFRELOCS=y
 CONFIG_PAX_KERNEXEC=y
 CONFIG_PAX_KERNEXEC_MODULE_TEXT=4
 
@@ -3743,6 +3837,7 @@ CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_NETWORK_XFRM=y
 # CONFIG_SECURITY_PATH is not set
 CONFIG_INTEL_TXT=y
+# CONFIG_SECURITY_SELINUX is not set
 # CONFIG_SECURITY_TOMOYO is not set
 # CONFIG_IMA is not set
 # CONFIG_DEFAULT_SECURITY_SELINUX is not set
@@ -3777,6 +3872,7 @@ CONFIG_CRYPTO_RNG2=y
 CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=m
 CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_TESTS=y
 CONFIG_CRYPTO_GF128MUL=m
 # CONFIG_CRYPTO_NULL is not set
 CONFIG_CRYPTO_PCRYPT=m
@@ -3901,6 +3997,7 @@ CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
 CONFIG_CRC7=m
 CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_LZO_COMPRESS=m
diff --git a/pkgs/core/kernel/kernel.nm b/pkgs/core/kernel/kernel.nm
index 49201b7..be7887b 100644
--- a/pkgs/core/kernel/kernel.nm
+++ b/pkgs/core/kernel/kernel.nm
@@ -25,8 +25,8 @@
 include $(PKGROOT)/Include
 
 PKG_NAME       = linux
-PKG_VER        = 2.6.34.1
-PKG_REL        = 0
+PKG_VER        = 2.6.35.4
+PKG_REL        = 1
 
 PKG_MAINTAINER = Michael Tremer <michael.tremer at ipfire.org>
 PKG_GROUP      = System/Kernels
@@ -34,7 +34,8 @@ PKG_URL        = http://www.kernel.org/
 PKG_LICENSE    = GPLv2
 PKG_SUMMARY    = The Linux kernel.
 
-PKG_BUILD_DEPS+= dracut module-init-tools ncurses-devel perl
+PKG_BUILD_DEPS+= module-init-tools ncurses-devel perl
+PKG_DEPS-kernel= dracut
 
 define PKG_DESCRIPTION
 	The kernel package contains the Linux kernel (vmlinuz), the core of any \
@@ -92,9 +93,6 @@ define STAGE_INSTALL
 
 	-mkdir -pv $(BUILDROOT)/lib/modules/$(FULLVER)/extra
 
-	dracut -v --kmoddir $(BUILDROOT)/lib/modules/$(FULLVER) \
-		$(BUILDROOT)/boot/initrd-$(FULLVER).img $(FULLVER)
-
 	rm -vf $(BUILDROOT)/lib/modules/$(FULLVER)/{build,source}
 
 	# Install the header files
diff --git a/pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch \
b/pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch deleted file mode 100644
index 80377b2..0000000
--- a/pkgs/core/kernel/patches/aufs2-2.6.33.1-1.patch
+++ /dev/null
@@ -1,26270 +0,0 @@
-diff -Nur linux-2.6.33.1-vanilla/Documentation/ABI/testing/debugfs-aufs \
                linux-2.6.33.1/Documentation/ABI/testing/debugfs-aufs
---- linux-2.6.33.1-vanilla/Documentation/ABI/testing/debugfs-aufs	1970-01-01 \
                01:00:00.000000000 +0100
-+++ linux-2.6.33.1/Documentation/ABI/testing/debugfs-aufs	2010-04-05 \
                16:48:57.000000000 +0200
-@@ -0,0 +1,40 @@
-+What:		/debug/aufs/si_<id>/
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+Description:
-+		Under /debug/aufs, a directory named si_<id> is created
-+		per aufs mount, where <id> is a unique id generated
-+		internally.
-+
-+What:		/debug/aufs/si_<id>/xib
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+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
-+		Documentation/filesystems/aufs/aufs.5 in detail.
-+
-+What:		/debug/aufs/si_<id>/xino0, xino1 ... xinoN
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+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
-+		Documentation/filesystems/aufs/aufs.5 in detail.
-+
-+What:		/debug/aufs/si_<id>/xigen
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+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
-+		Documentation/filesystems/aufs/aufs.5 in detail.
-diff -Nur linux-2.6.33.1-vanilla/Documentation/ABI/testing/sysfs-aufs \
                linux-2.6.33.1/Documentation/ABI/testing/sysfs-aufs
---- linux-2.6.33.1-vanilla/Documentation/ABI/testing/sysfs-aufs	1970-01-01 \
                01:00:00.000000000 +0100
-+++ linux-2.6.33.1/Documentation/ABI/testing/sysfs-aufs	2010-04-05 \
                16:48:57.000000000 +0200
-@@ -0,0 +1,25 @@
-+What:		/sys/fs/aufs/si_<id>/
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+Description:
-+		Under /sys/fs/aufs, a directory named si_<id> is created
-+		per aufs mount, where <id> is a unique id generated
-+		internally.
-+
-+What:		/sys/fs/aufs/si_<id>/br0, br1 ... brN
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+Description:
-+		It shows the abolute path of a member directory (which
-+		is called branch) in aufs, and its permission.
-+
-+What:		/sys/fs/aufs/si_<id>/xi_path
-+Date:		March 2009
-+Contact:	J. R. Okajima <hooanon05 at yahoo.co.jp>
-+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
-+		Documentation/filesystems/aufs/aufs.5 in detail.
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/aufs.h linux-2.6.33.1/fs/aufs/aufs.h
---- linux-2.6.33.1-vanilla/fs/aufs/aufs.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/aufs.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,59 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 "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 -Nur linux-2.6.33.1-vanilla/fs/aufs/branch.c linux-2.6.33.1/fs/aufs/branch.c
---- linux-2.6.33.1-vanilla/fs/aufs/branch.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/branch.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,996 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * branch management
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/statfs.h>
-+#include "aufs.h"
-+
-+/*
-+ * free a single branch
-+ */
-+static void au_br_do_free(struct au_branch *br)
-+{
-+	int i;
-+	struct au_wbr *wbr;
-+
-+	if (br->br_xino.xi_file)
-+		fput(br->br_xino.xi_file);
-+	mutex_destroy(&br->br_xino.xi_nondir_mtx);
-+
-+	AuDebugOn(atomic_read(&br->br_count));
-+
-+	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);
-+	}
-+
-+	/* some filesystems acquire extra lock */
-+	/* lockdep_off(); */
-+	mntput(br->br_mnt);
-+	/* lockdep_on(); */
-+
-+	kfree(wbr);
-+	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_bend + 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, bend;
-+
-+	bend = au_sbend(sb);
-+	for (bindex = 0; bindex <= bend; 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_d1,
-+			struct dentry *h_d2)
-+{
-+	if (unlikely(h_d1 == h_d2))
-+		return 1;
-+	return !!au_test_subdir(h_d1, h_d2)
-+		|| !!au_test_subdir(h_d2, h_d1)
-+		|| au_test_loopback_overlap(sb, h_d1, h_d2)
-+		|| au_test_loopback_overlap(sb, h_d2, h_d1);
-+}
-+
-+/*
-+ * 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;
-+	int err;
-+
-+	err = -ENOMEM;
-+	root = sb->s_root;
-+	add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
-+	if (unlikely(!add_branch))
-+		goto out;
-+
-+	add_branch->br_wbr = NULL;
-+	if (au_br_writable(perm)) {
-+		/* may be freed separately at changing the branch permission */
-+		add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
-+					     GFP_NOFS);
-+		if (unlikely(!add_branch->br_wbr))
-+			goto out_br;
-+	}
-+
-+	err = au_sbr_realloc(au_sbi(sb), new_nbranch);
-+	if (!err)
-+		err = au_di_realloc(au_di(root), new_nbranch);
-+	if (!err)
-+		err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
-+	if (!err)
-+		return add_branch; /* success */
-+
-+	kfree(add_branch->br_wbr);
-+
-+ out_br:
-+	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 bend, bindex;
-+	struct dentry *root;
-+	struct inode *inode, *h_inode;
-+
-+	root = sb->s_root;
-+	bend = au_sbend(sb);
-+	if (unlikely(bend >= 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 <= bend)) {
-+		pr_err("number of branches exceeded %s\n", add->pathname);
-+		goto out;
-+	}
-+
-+	err = -EDOM;
-+	if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
-+		pr_err("bad index %d\n", add->bindex);
-+		goto out;
-+	}
-+
-+	inode = add->path.dentry->d_inode;
-+	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;
-+	}
-+
-+	err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
-+	if (unlikely(err))
-+		goto out;
-+
-+	if (bend < 0)
-+		return 0; /* success */
-+
-+	err = -EINVAL;
-+	for (bindex = 0; bindex <= bend; 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_inode = au_h_dptr(root, 0)->d_inode;
-+		if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
-+		    || h_inode->i_uid != inode->i_uid
-+		    || h_inode->i_gid != inode->i_gid)
-+			pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
-+				   add->pathname,
-+				   inode->i_uid, inode->i_gid,
-+				   (inode->i_mode & S_IALLUGO),
-+				   h_inode->i_uid, h_inode->i_gid,
-+				   (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, struct dentry *h_root)
-+{
-+	int err, old_perm;
-+	aufs_bindex_t bindex;
-+	struct mutex *h_mtx;
-+	struct au_wbr *wbr;
-+	struct au_hinode *hdir;
-+
-+	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(sb->s_root->d_inode, bindex);
-+		au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
-+	} else {
-+		h_mtx = &h_root->d_inode->i_mutex;
-+		mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
-+	}
-+	if (!wbr)
-+		err = au_wh_init(h_root, br, sb);
-+	else {
-+		wbr_wh_write_lock(wbr);
-+		err = au_wh_init(h_root, br, sb);
-+		wbr_wh_write_unlock(wbr);
-+	}
-+	if (hdir)
-+		au_hn_imtx_unlock(hdir);
-+	else
-+		mutex_unlock(h_mtx);
-+	br->br_perm = old_perm;
-+
-+	if (!err && wbr && !au_br_writable(new_perm)) {
-+		kfree(wbr);
-+		br->br_wbr = NULL;
-+	}
-+
-+	return err;
-+}
-+
-+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
-+		       int perm, struct path *path)
-+{
-+	int err;
-+	struct kstatfs kst;
-+	struct au_wbr *wbr;
-+	struct dentry *h_dentry;
-+
-+	wbr = br->br_wbr;
-+	au_rw_init(&wbr->wbr_wh_rwsem);
-+	memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
-+	atomic_set(&wbr->wbr_wh_running, 0);
-+	wbr->wbr_bytes = 0;
-+
-+	/*
-+	 * a limit for rmdir/rename a dir
-+	 * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
-+	 */
-+	h_dentry = path->dentry;
-+	err = vfs_statfs(h_dentry, &kst);
-+	if (unlikely(err))
-+		goto out;
-+	err = -EINVAL;
-+	if (kst.f_namelen >= NAME_MAX)
-+		err = au_br_init_wh(sb, br, perm, h_dentry);
-+	else
-+		pr_err("%.*s(%s), unsupported namelen %ld\n",
-+		       AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
-+		       kst.f_namelen);
-+
-+ out:
-+	return err;
-+}
-+
-+/* intialize a new branch */
-+static int au_br_init(struct au_branch *br, struct super_block *sb,
-+		      struct au_opt_add *add)
-+{
-+	int err;
-+
-+	err = 0;
-+	memset(&br->br_xino, 0, sizeof(br->br_xino));
-+	mutex_init(&br->br_xino.xi_nondir_mtx);
-+	br->br_perm = add->perm;
-+	br->br_mnt = add->path.mnt; /* set first, mntget() later */
-+	atomic_set(&br->br_count, 0);
-+	br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
-+	atomic_set(&br->br_xino_running, 0);
-+	br->br_id = au_new_br_id(sb);
-+
-+	if (au_br_writable(add->perm)) {
-+		err = au_wbr_init(br, sb, add->perm, &add->path);
-+		if (unlikely(err))
-+			goto out;
-+	}
-+
-+	if (au_opt_test(au_mntflags(sb), XINO)) {
-+		err = au_xino_br(sb, br, add->path.dentry->d_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;
-+		}
-+	}
-+
-+	sysaufs_br_init(br);
-+	mntget(add->path.mnt);
-+
-+ 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 bend,
-+			     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_bend++;
-+	if (unlikely(bend < 0))
-+		sbinfo->si_bend = 0;
-+}
-+
-+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
-+			     aufs_bindex_t bend, aufs_bindex_t amount)
-+{
-+	struct au_hdentry *hdp;
-+
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	hdp = dinfo->di_hdentry + bindex;
-+	memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
-+	au_h_dentry_init(hdp);
-+	dinfo->di_bend++;
-+	if (unlikely(bend < 0))
-+		dinfo->di_bstart = 0;
-+}
-+
-+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
-+			     aufs_bindex_t bend, aufs_bindex_t amount)
-+{
-+	struct au_hinode *hip;
-+
-+	AuRwMustWriteLock(&iinfo->ii_rwsem);
-+
-+	hip = iinfo->ii_hinode + bindex;
-+	memmove(hip + 1, hip, sizeof(*hip) * amount);
-+	hip->hi_inode = NULL;
-+	au_hn_init(hip);
-+	iinfo->ii_bend++;
-+	if (unlikely(bend < 0))
-+		iinfo->ii_bstart = 0;
-+}
-+
-+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
-+			 struct au_branch *br, aufs_bindex_t bindex)
-+{
-+	struct dentry *root;
-+	struct inode *root_inode;
-+	aufs_bindex_t bend, amount;
-+
-+	root = sb->s_root;
-+	root_inode = root->d_inode;
-+	au_plink_maint_block(sb);
-+	bend = au_sbend(sb);
-+	amount = bend + 1 - bindex;
-+	au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
-+	au_br_do_add_hdp(au_di(root), bindex, bend, amount);
-+	au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
-+	au_set_h_dptr(root, bindex, dget(h_dentry));
-+	au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
-+		      /*flags*/0);
-+}
-+
-+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
-+{
-+	int err;
-+	aufs_bindex_t bend, add_bindex;
-+	struct dentry *root, *h_dentry;
-+	struct inode *root_inode;
-+	struct au_branch *add_branch;
-+
-+	root = sb->s_root;
-+	root_inode = root->d_inode;
-+	IMustLock(root_inode);
-+	err = test_add(sb, add, remount);
-+	if (unlikely(err < 0))
-+		goto out;
-+	if (err) {
-+		err = 0;
-+		goto out; /* success */
-+	}
-+
-+	bend = au_sbend(sb);
-+	add_branch = au_br_alloc(sb, bend + 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;
-+	h_dentry = add->path.dentry;
-+	if (!remount)
-+		au_br_do_add(sb, h_dentry, add_branch, add_bindex);
-+	else {
-+		sysaufs_brs_del(sb, add_bindex);
-+		au_br_do_add(sb, h_dentry, add_branch, add_bindex);
-+		sysaufs_brs_add(sb, add_bindex);
-+	}
-+
-+	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, h_dentry->d_inode);
-+
-+	/*
-+	 * this test/set prevents aufs from handling unnecesary notify events
-+	 * of xino files, in a 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_dentry->d_parent == h_dentry)
-+		au_xino_brid_set(sb, add_branch->br_id);
-+
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * 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)
-+
-+/*
-+ * test if the branch is deletable or not.
-+ */
-+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
-+			    unsigned int sigen)
-+{
-+	int err, i, j, ndentry;
-+	aufs_bindex_t bstart, bend;
-+	unsigned char verbose;
-+	struct au_dcsub_pages dpages;
-+	struct au_dpage *dpage;
-+	struct dentry *d;
-+	struct inode *inode;
-+
-+	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;
-+
-+	verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
-+	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(!atomic_read(&d->d_count));
-+			inode = d->d_inode;
-+			if (au_digen(d) == sigen && au_iigen(inode) == sigen)
-+				di_read_lock_child(d, AuLock_IR);
-+			else {
-+				di_write_lock_child(d);
-+				err = au_reval_dpath(d, sigen);
-+				if (!err)
-+					di_downgrade_lock(d, AuLock_IR);
-+				else {
-+					di_write_unlock(d);
-+					break;
-+				}
-+			}
-+
-+			bstart = au_dbstart(d);
-+			bend = au_dbend(d);
-+			if (bstart <= bindex
-+			    && bindex <= bend
-+			    && au_h_dptr(d, bindex)
-+			    && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
-+				err = -EBUSY;
-+				AuVerbose(verbose, "busy %.*s\n", AuDLNPair(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)
-+{
-+	int err;
-+	struct inode *i;
-+	aufs_bindex_t bstart, bend;
-+	unsigned char verbose;
-+
-+	err = 0;
-+	verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
-+	list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
-+		AuDebugOn(!atomic_read(&i->i_count));
-+		if (!list_empty(&i->i_dentry))
-+			continue;
-+
-+		if (au_iigen(i) == sigen)
-+			ii_read_lock_child(i);
-+		else {
-+			ii_write_lock_child(i);
-+			err = au_refresh_hinode_self(i, /*do_attr*/1);
-+			if (!err)
-+				ii_downgrade_lock(i);
-+			else {
-+				ii_write_unlock(i);
-+				break;
-+			}
-+		}
-+
-+		bstart = au_ibstart(i);
-+		bend = au_ibend(i);
-+		if (bstart <= bindex
-+		    && bindex <= bend
-+		    && au_h_iptr(i, bindex)
-+		    && (!S_ISDIR(i->i_mode) || bstart == bend)) {
-+			err = -EBUSY;
-+			AuVerbose(verbose, "busy i%lu\n", i->i_ino);
-+			ii_read_unlock(i);
-+			break;
-+		}
-+		ii_read_unlock(i);
-+	}
-+
-+	return err;
-+}
-+
-+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
-+{
-+	int err;
-+	unsigned int sigen;
-+
-+	sigen = au_sigen(root->d_sb);
-+	DiMustNoWaiters(root);
-+	IiMustNoWaiters(root->d_inode);
-+	di_write_unlock(root);
-+	err = test_dentry_busy(root, bindex, sigen);
-+	if (!err)
-+		err = test_inode_busy(root->d_sb, bindex, sigen);
-+	di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
-+
-+	return err;
-+}
-+
-+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
-+			     const aufs_bindex_t bindex,
-+			     const aufs_bindex_t bend)
-+{
-+	struct au_branch **brp, **p;
-+
-+	AuRwMustWriteLock(&sbinfo->si_rwsem);
-+
-+	brp = sbinfo->si_branch + bindex;
-+	if (bindex < bend)
-+		memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
-+	sbinfo->si_branch[0 + bend] = NULL;
-+	sbinfo->si_bend--;
-+
-+	p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
-+	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 bend)
-+{
-+	struct au_hdentry *hdp, *p;
-+
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	hdp = dinfo->di_hdentry + bindex;
-+	if (bindex < bend)
-+		memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
-+	dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
-+	dinfo->di_bend--;
-+
-+	p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
-+	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 bend)
-+{
-+	struct au_hinode *hip, *p;
-+
-+	AuRwMustWriteLock(&iinfo->ii_rwsem);
-+
-+	hip = iinfo->ii_hinode + bindex;
-+	if (bindex < bend)
-+		memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
-+	iinfo->ii_hinode[0 + bend].hi_inode = NULL;
-+	au_hn_init(iinfo->ii_hinode + bend);
-+	iinfo->ii_bend--;
-+
-+	p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
-+	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 bend;
-+	struct au_sbinfo *sbinfo;
-+	struct dentry *root;
-+	struct inode *inode;
-+
-+	SiMustWriteLock(sb);
-+
-+	root = sb->s_root;
-+	inode = root->d_inode;
-+	au_plink_maint_block(sb);
-+	sbinfo = au_sbi(sb);
-+	bend = sbinfo->si_bend;
-+
-+	dput(au_h_dptr(root, bindex));
-+	au_hiput(au_hi(inode, bindex));
-+	au_br_do_free(br);
-+
-+	au_br_do_del_brp(sbinfo, bindex, bend);
-+	au_br_do_del_hdp(au_di(root), bindex, bend);
-+	au_br_do_del_hip(au_ii(inode), bindex, bend);
-+}
-+
-+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
-+{
-+	int err, rerr, i;
-+	unsigned int mnt_flags;
-+	aufs_bindex_t bindex, bend, br_id;
-+	unsigned char do_wh, verbose;
-+	struct au_branch *br;
-+	struct au_wbr *wbr;
-+
-+	err = 0;
-+	bindex = au_find_dbindex(sb->s_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);
-+	bend = au_sbend(sb);
-+	if (unlikely(!bend)) {
-+		AuVerbose(verbose, "no more branches left\n");
-+		goto out;
-+	}
-+	br = au_sbr(sb, bindex);
-+	i = atomic_read(&br->br_count);
-+	if (unlikely(i)) {
-+		AuVerbose(verbose, "%d file(s) opened\n", i);
-+		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(sb->s_root, bindex);
-+	if (unlikely(err)) {
-+		if (do_wh)
-+			goto out_wh;
-+		goto out;
-+	}
-+
-+	err = 0;
-+	br_id = br->br_id;
-+	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(sb->s_root->d_inode, /*force*/1);
-+		sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
-+	} else
-+		au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
-+	if (au_opt_test(mnt_flags, PLINK))
-+		au_plink_half_refresh(sb, br_id);
-+
-+	if (au_xino_brid(sb) == br->br_id)
-+		au_xino_brid_set(sb, -1);
-+	goto out; /* success */
-+
-+ out_wh:
-+	/* revert */
-+	rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
-+	if (rerr)
-+		pr_warning("failed re-creating base whiteout, %s. (%d)\n",
-+			   del->pathname, rerr);
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * change a branch permission
-+ */
-+
-+static void au_warn_ima(void)
-+{
-+#ifdef CONFIG_IMA
-+	/* since it doesn't support mark_files_ro() */
-+	pr_warning("RW -> RO makes IMA to produce wrong message");
-+#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;
-+	unsigned long n, ul, bytes, files;
-+	aufs_bindex_t bstart;
-+	struct file *file, *hf, **a;
-+	const int step_bytes = 1024, /* memory allocation unit */
-+		step_files = step_bytes / sizeof(*a);
-+
-+	err = -ENOMEM;
-+	n = 0;
-+	bytes = step_bytes;
-+	files = step_files;
-+	a = kmalloc(bytes, GFP_NOFS);
-+	if (unlikely(!a))
-+		goto out;
-+
-+	/* no need file_list_lock() since sbinfo is locked? defered? */
-+	list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
-+		if (special_file(file->f_dentry->d_inode->i_mode))
-+			continue;
-+
-+		AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
-+		fi_read_lock(file);
-+		if (unlikely(au_test_mmapped(file))) {
-+			err = -EBUSY;
-+			FiMustNoWaiters(file);
-+			fi_read_unlock(file);
-+			goto out_free;
-+		}
-+
-+		bstart = au_fbstart(file);
-+		if (!S_ISREG(file->f_dentry->d_inode->i_mode)
-+		    || !(file->f_mode & FMODE_WRITE)
-+		    || bstart != bindex) {
-+			FiMustNoWaiters(file);
-+			fi_read_unlock(file);
-+			continue;
-+		}
-+
-+		hf = au_h_fptr(file, bstart);
-+		FiMustNoWaiters(file);
-+		fi_read_unlock(file);
-+
-+		if (n < files)
-+			a[n++] = hf;
-+		else {
-+			void *p;
-+
-+			err = -ENOMEM;
-+			bytes += step_bytes;
-+			files += step_files;
-+			p = krealloc(a, bytes, GFP_NOFS);
-+			if (p) {
-+				a = p;
-+				a[n++] = hf;
-+			} else
-+				goto out_free;
-+		}
-+	}
-+
-+	err = 0;
-+	if (n)
-+		au_warn_ima();
-+	for (ul = 0; ul < n; ul++) {
-+		/* todo: already flushed? */
-+		/* cf. fs/super.c:mark_files_ro() */
-+		hf = a[ul];
-+		hf->f_mode &= ~FMODE_WRITE;
-+		if (!file_check_writeable(hf)) {
-+			file_release_write(hf);
-+			mnt_drop_write(hf->f_vfsmnt);
-+		}
-+	}
-+
-+ out_free:
-+	kfree(a);
-+ out:
-+	return err;
-+}
-+
-+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
-+	      int *do_update)
-+{
-+	int err, rerr;
-+	aufs_bindex_t bindex;
-+	struct path path;
-+	struct dentry *root;
-+	struct au_branch *br;
-+
-+	root = sb->s_root;
-+	au_plink_maint_block(sb);
-+	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(mod->h_root->d_inode, mod->perm, mod->path);
-+	if (unlikely(err))
-+		goto out;
-+
-+	br = au_sbr(sb, bindex);
-+	if (br->br_perm == mod->perm)
-+		return 0; /* success */
-+
-+	if (au_br_writable(br->br_perm)) {
-+		/* remove whiteout base */
-+		err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
-+		if (unlikely(err))
-+			goto out;
-+
-+		if (!au_br_writable(mod->perm)) {
-+			/* rw --> ro, file might be mmapped */
-+			DiMustNoWaiters(root);
-+			IiMustNoWaiters(root->d_inode);
-+			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 = kmalloc(sizeof(*br->br_wbr),
-+						     GFP_NOFS);
-+				if (br->br_wbr) {
-+					path.mnt = br->br_mnt;
-+					path.dentry = mod->h_root;
-+					rerr = au_wbr_init(br, sb, br->br_perm,
-+							   &path);
-+				}
-+				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 = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
-+		if (br->br_wbr) {
-+			path.mnt = br->br_mnt;
-+			path.dentry = mod->h_root;
-+			err = au_wbr_init(br, sb, mod->perm, &path);
-+			if (unlikely(err)) {
-+				kfree(br->br_wbr);
-+				br->br_wbr = NULL;
-+			}
-+		}
-+	}
-+
-+	if (!err) {
-+		*do_update |= need_sigen_inc(br->br_perm, mod->perm);
-+		br->br_perm = mod->perm;
-+	}
-+
-+ out:
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/branch.h linux-2.6.33.1/fs/aufs/branch.h
---- linux-2.6.33.1-vanilla/fs/aufs/branch.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/branch.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,219 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * branch filesystems and xino for them
-+ */
-+
-+#ifndef __AUFS_BRANCH_H__
-+#define __AUFS_BRANCH_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/mount.h>
-+#include <linux/aufs_type.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
-+};
-+
-+/* 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;
-+};
-+
-+/* protected by superblock rwsem */
-+struct au_branch {
-+	struct au_xino_file	br_xino;
-+
-+	aufs_bindex_t		br_id;
-+
-+	int			br_perm;
-+	struct vfsmount		*br_mnt;
-+	atomic_t		br_count;
-+
-+	struct au_wbr		*br_wbr;
-+
-+	/* xino truncation */
-+	blkcnt_t		br_xino_upper;	/* watermark in blocks */
-+	atomic_t		br_xino_running;
-+
-+#ifdef CONFIG_SYSFS
-+	/* an entry under sysfs per mount-point */
-+	char			br_name[8];
-+	struct attribute	br_attr;
-+#endif
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* branch permission and attribute */
-+enum {
-+	AuBrPerm_RW,		/* writable, linkable wh */
-+	AuBrPerm_RO,		/* readonly, no wh */
-+	AuBrPerm_RR,		/* natively readonly, no wh */
-+
-+	AuBrPerm_RWNoLinkWH,	/* un-linkable whiteouts */
-+
-+	AuBrPerm_ROWH,		/* whiteout-able */
-+	AuBrPerm_RRWH,		/* whiteout-able */
-+
-+	AuBrPerm_Last
-+};
-+
-+static inline int au_br_writable(int brperm)
-+{
-+	return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
-+}
-+
-+static inline int au_br_whable(int brperm)
-+{
-+	return brperm == AuBrPerm_RW
-+		|| brperm == AuBrPerm_ROWH
-+		|| brperm == AuBrPerm_RRWH;
-+}
-+
-+static inline int au_br_rdonly(struct au_branch *br)
-+{
-+	return ((br->br_mnt->mnt_sb->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 && brperm != AuBrPerm_RRWH;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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);
-+struct au_opt_mod;
-+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
-+	      int *do_update);
-+
-+/* xino.c */
-+static const loff_t au_loff_max = LLONG_MAX;
-+
-+int au_xib_trunc(struct super_block *sb);
-+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
-+		   loff_t *pos);
-+ssize_t xino_fwrite(au_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);
-+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
-+		   ino_t ino);
-+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
-+		  ino_t ino);
-+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_sbr(sb, bindex)->br_mnt;
-+}
-+
-+static inline
-+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+	return au_sbr_mnt(sb, bindex)->mnt_sb;
-+}
-+
-+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+	atomic_dec_return(&au_sbr(sb, bindex)->br_count);
-+}
-+
-+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)
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_BRANCH_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/conf.mk linux-2.6.33.1/fs/aufs/conf.mk
---- linux-2.6.33.1-vanilla/fs/aufs/conf.mk	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/conf.mk	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,33 @@
-+
-+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
-+
-+define AuConf
-+ifdef ${1}
-+AuConfStr += ${1}=${${1}}
-+endif
-+endef
-+
-+$(foreach i, BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
-+	HNOTIFY HFSNOTIFY HINOTIFY \
-+	EXPORT INO_T_64 \
-+	RDU \
-+	SP_IATTR \
-+	SHWH \
-+	BR_RAMFS \
-+	BR_FUSE POLL \
-+	BR_HFSPLUS \
-+	BDEV_LOOP \
-+	DEBUG MAGIC_SYSRQ, \
-+	$(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}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/cpup.c linux-2.6.33.1/fs/aufs/cpup.c
---- linux-2.6.33.1-vanilla/fs/aufs/cpup.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/cpup.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,1049 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * copy-up functions, see wbr_policy.c for copy-down
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/fs_stack.h>
-+#include <linux/mm.h>
-+#include <linux/uaccess.h>
-+#include "aufs.h"
-+
-+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
-+{
-+	const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
-+		| S_NOATIME | S_NOCMTIME;
-+
-+	dst->i_flags |= src->i_flags & ~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_ibstart(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, bend;
-+
-+	sb = inode->i_sb;
-+	bindex = au_ibstart(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;
-+
-+	inode->i_nlink = 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)) {
-+		bend = au_ibend(inode);
-+		for (bindex++; bindex <= bend; 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_ibstart(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);
-+}
-+
-+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_ibstart(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 = h_path->dentry->d_inode;
-+	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;
-+
-+	err = vfsub_notify_change(&dt->dt_h_path, &attr);
-+	if (unlikely(err))
-+		pr_warning("restoring timestamps failed(%d). ignored\n", err);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static noinline_for_stack
-+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
-+{
-+	int err, sbits;
-+	struct iattr ia;
-+	struct path h_path;
-+	struct inode *h_isrc, *h_idst;
-+
-+	h_path.dentry = au_h_dptr(dst, bindex);
-+	h_idst = h_path.dentry->d_inode;
-+	h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
-+	h_isrc = h_src->d_inode;
-+	ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
-+		| ATTR_ATIME | ATTR_MTIME
-+		| ATTR_ATIME_SET | ATTR_MTIME_SET;
-+	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);
-+	err = vfsub_notify_change(&h_path, &ia);
-+
-+	/* 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);
-+	}
-+
-+	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;
-+			}
-+		} 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_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 = &dst->f_dentry->d_inode->i_mutex;
-+			mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
-+			err = vfsub_notify_change(&dst->f_path, ia);
-+			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_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)
-+		kfree(buf);
-+	else
-+		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 dentry *dentry, aufs_bindex_t bdst,
-+			aufs_bindex_t bsrc, loff_t len)
-+{
-+	int err, i;
-+	enum { SRC, DST };
-+	struct {
-+		aufs_bindex_t bindex;
-+		unsigned int flags;
-+		struct dentry *dentry;
-+		struct file *file;
-+		void *label, *label_file;
-+	} *f, file[] = {
-+		{
-+			.bindex = bsrc,
-+			.flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
-+			.file = NULL,
-+			.label = &&out,
-+			.label_file = &&out_src
-+		},
-+		{
-+			.bindex = bdst,
-+			.flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
-+			.file = NULL,
-+			.label = &&out_src,
-+			.label_file = &&out_dst
-+		}
-+	};
-+	struct super_block *sb;
-+
-+	/* bsrc branch can be ro/rw. */
-+	sb = dentry->d_sb;
-+	f = file;
-+	for (i = 0; i < 2; i++, f++) {
-+		f->dentry = au_h_dptr(dentry, f->bindex);
-+		f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
-+		err = PTR_ERR(f->file);
-+		if (IS_ERR(f->file))
-+			goto *f->label;
-+		err = -EINVAL;
-+		if (unlikely(!f->file->f_op))
-+			goto *f->label_file;
-+	}
-+
-+	/* try stopping to update while we copyup */
-+	IMustLock(file[SRC].dentry->d_inode);
-+	err = au_copy_file(file[DST].file, file[SRC].file, len);
-+
-+ out_dst:
-+	fput(file[DST].file);
-+	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 dentry *dentry, aufs_bindex_t bdst,
-+			      aufs_bindex_t bsrc, loff_t len,
-+			      struct inode *h_dir, struct path *h_path)
-+{
-+	int err, rerr;
-+	loff_t l;
-+
-+	err = 0;
-+	l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
-+	if (len == -1 || l < len)
-+		len = l;
-+	if (len)
-+		err = au_cp_regular(dentry, bdst, bsrc, len);
-+	if (!err)
-+		goto out; /* success */
-+
-+	rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
-+	if (rerr) {
-+		AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
-+			AuDLNPair(h_path->dentry), err, rerr);
-+		err = -EIO;
-+	}
-+
-+ 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;
-+	char *sym;
-+
-+	err = -ENOSYS;
-+	if (unlikely(!h_src->d_inode->i_op->readlink))
-+		goto out;
-+
-+	err = -ENOMEM;
-+	sym = __getname_gfp(GFP_NOFS);
-+	if (unlikely(!sym))
-+		goto out;
-+
-+	old_fs = get_fs();
-+	set_fs(KERNEL_DS);
-+	symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
-+						PATH_MAX);
-+	err = symlen;
-+	set_fs(old_fs);
-+
-+	if (symlen > 0) {
-+		sym[symlen] = 0;
-+		err = vfsub_symlink(h_dir, h_path, sym);
-+	}
-+	__putname(sym);
-+
-+ out:
-+	return err;
-+}
-+
-+/* return with the lower dst inode is locked */
-+static noinline_for_stack
-+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
-+	       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+	       struct dentry *dst_parent)
-+{
-+	int err;
-+	umode_t mode;
-+	unsigned int mnt_flags;
-+	unsigned char isdir;
-+	const unsigned char do_dt = !!au_ftest_cpup(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(dentry, bsrc);
-+	h_inode = h_src->d_inode;
-+	AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
-+
-+	/* try stopping to be referenced while we are creating */
-+	h_dst = au_h_dptr(dentry, bdst);
-+	h_parent = h_dst->d_parent; /* dir inode is locked */
-+	h_dir = h_parent->d_inode;
-+	IMustLock(h_dir);
-+	AuDebugOn(h_parent != h_dst->d_parent);
-+
-+	sb = dentry->d_sb;
-+	h_path.mnt = au_sbr_mnt(sb, bdst);
-+	if (do_dt) {
-+		h_path.dentry = h_parent;
-+		au_dtime_store(&dt, dst_parent, &h_path);
-+	}
-+	h_path.dentry = h_dst;
-+
-+	isdir = 0;
-+	mode = h_inode->i_mode;
-+	switch (mode & S_IFMT) {
-+	case S_IFREG:
-+		/* try stopping to update while we are referencing */
-+		IMustLock(h_inode);
-+		err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
-+		if (!err)
-+			err = au_do_cpup_regular
-+				(dentry, bdst, bsrc, len,
-+				 au_h_iptr(dst_parent->d_inode, bdst), &h_path);
-+		break;
-+	case S_IFDIR:
-+		isdir = 1;
-+		err = vfsub_mkdir(h_dir, &h_path, mode);
-+		if (!err) {
-+			/*
-+			 * strange behaviour from the users view,
-+			 * particularry setattr case
-+			 */
-+			if (au_ibstart(dst_parent->d_inode) == bdst)
-+				au_cpup_attr_nlink(dst_parent->d_inode,
-+						   /*force*/1);
-+			au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
-+		}
-+		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;
-+	}
-+
-+	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
-+	    /* todo: unnecessary? */
-+	    /* && dentry->d_inode->i_nlink == 1 */
-+	    && bdst < bsrc
-+	    && !au_ftest_cpup(flags, KEEPLINO))
-+		au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
-+		/* ignore this error */
-+
-+	if (do_dt)
-+		au_dtime_revert(&dt);
-+	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.
-+ */
-+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
-+			  aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+			  struct dentry *dst_parent)
-+{
-+	int err, rerr;
-+	aufs_bindex_t old_ibstart;
-+	unsigned char isdir, plink;
-+	struct au_dtime dt;
-+	struct path h_path;
-+	struct dentry *h_src, *h_dst, *h_parent;
-+	struct inode *dst_inode, *h_dir, *inode;
-+	struct super_block *sb;
-+
-+	AuDebugOn(bsrc <= bdst);
-+
-+	sb = dentry->d_sb;
-+	h_path.mnt = au_sbr_mnt(sb, bdst);
-+	h_dst = au_h_dptr(dentry, bdst);
-+	h_parent = h_dst->d_parent; /* dir inode is locked */
-+	h_dir = h_parent->d_inode;
-+	IMustLock(h_dir);
-+
-+	h_src = au_h_dptr(dentry, bsrc);
-+	inode = dentry->d_inode;
-+
-+	if (!dst_parent)
-+		dst_parent = dget_parent(dentry);
-+	else
-+		dget(dst_parent);
-+
-+	plink = !!au_opt_test(au_mntflags(sb), PLINK);
-+	dst_inode = au_h_iptr(inode, bdst);
-+	if (dst_inode) {
-+		if (unlikely(!plink)) {
-+			err = -EIO;
-+			AuIOErr("i%lu exists on a upper branch "
-+				"but plink is disabled\n", inode->i_ino);
-+			goto out;
-+		}
-+
-+		if (dst_inode->i_nlink) {
-+			const int do_dt = au_ftest_cpup(flags, DTIME);
-+
-+			h_src = au_plink_lkup(inode, bdst);
-+			err = PTR_ERR(h_src);
-+			if (IS_ERR(h_src))
-+				goto out;
-+			if (unlikely(!h_src->d_inode)) {
-+				err = -EIO;
-+				AuIOErr("i%lu exists on a upper branch "
-+					"but plink is broken\n", inode->i_ino);
-+				dput(h_src);
-+				goto out;
-+			}
-+
-+			if (do_dt) {
-+				h_path.dentry = h_parent;
-+				au_dtime_store(&dt, dst_parent, &h_path);
-+			}
-+			h_path.dentry = h_dst;
-+			err = vfsub_link(h_src, h_dir, &h_path);
-+			if (do_dt)
-+				au_dtime_revert(&dt);
-+			dput(h_src);
-+			goto out;
-+		} else
-+			/* todo: cpup_wh_file? */
-+			/* udba work */
-+			au_update_brange(inode, 1);
-+	}
-+
-+	old_ibstart = au_ibstart(inode);
-+	err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
-+	if (unlikely(err))
-+		goto out;
-+	dst_inode = h_dst->d_inode;
-+	mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
-+
-+	err = cpup_iattr(dentry, bdst, h_src);
-+	isdir = S_ISDIR(dst_inode->i_mode);
-+	if (!err) {
-+		if (bdst < old_ibstart)
-+			au_set_ibstart(inode, bdst);
-+		au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
-+			      au_hi_flags(inode, isdir));
-+		mutex_unlock(&dst_inode->i_mutex);
-+		if (!isdir
-+		    && h_src->d_inode->i_nlink > 1
-+		    && plink)
-+			au_plink_append(inode, bdst, h_dst);
-+		goto out; /* success */
-+	}
-+
-+	/* revert */
-+	h_path.dentry = h_parent;
-+	mutex_unlock(&dst_inode->i_mutex);
-+	au_dtime_store(&dt, dst_parent, &h_path);
-+	h_path.dentry = h_dst;
-+	if (!isdir)
-+		rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
-+	else
-+		rerr = vfsub_rmdir(h_dir, &h_path);
-+	au_dtime_revert(&dt);
-+	if (rerr) {
-+		AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
-+		err = -EIO;
-+	}
-+
-+ out:
-+	dput(dst_parent);
-+	return err;
-+}
-+
-+struct au_cpup_single_args {
-+	int *errp;
-+	struct dentry *dentry;
-+	aufs_bindex_t bdst, bsrc;
-+	loff_t len;
-+	unsigned int flags;
-+	struct dentry *dst_parent;
-+};
-+
-+static void au_call_cpup_single(void *args)
-+{
-+	struct au_cpup_single_args *a = args;
-+	*a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
-+				  a->flags, a->dst_parent);
-+}
-+
-+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
-+		       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+		       struct dentry *dst_parent)
-+{
-+	int err, wkq_err;
-+	umode_t mode;
-+	struct dentry *h_dentry;
-+
-+	h_dentry = au_h_dptr(dentry, bsrc);
-+	mode = h_dentry->d_inode->i_mode & S_IFMT;
-+	if ((mode != S_IFCHR && mode != S_IFBLK)
-+	    || capable(CAP_MKNOD))
-+		err = au_cpup_single(dentry, bdst, bsrc, len, flags,
-+				     dst_parent);
-+	else {
-+		struct au_cpup_single_args args = {
-+			.errp		= &err,
-+			.dentry		= dentry,
-+			.bdst		= bdst,
-+			.bsrc		= bsrc,
-+			.len		= len,
-+			.flags		= flags,
-+			.dst_parent	= dst_parent
-+		};
-+		wkq_err = au_wkq_wait(au_call_cpup_single, &args);
-+		if (unlikely(wkq_err))
-+			err = wkq_err;
-+	}
-+
-+	return err;
-+}
-+
-+/*
-+ * copyup the @dentry from the first active lower branch to @bdst,
-+ * using au_cpup_single().
-+ */
-+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+			  unsigned int flags)
-+{
-+	int err;
-+	aufs_bindex_t bsrc, bend;
-+
-+	bend = au_dbend(dentry);
-+	for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
-+		if (au_h_dptr(dentry, bsrc))
-+			break;
-+
-+	err = au_lkup_neg(dentry, bdst);
-+	if (!err) {
-+		err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
-+		if (!err)
-+			return 0; /* success */
-+
-+		/* revert */
-+		au_set_h_dptr(dentry, bdst, NULL);
-+		au_set_dbstart(dentry, bsrc);
-+	}
-+
-+	return err;
-+}
-+
-+struct au_cpup_simple_args {
-+	int *errp;
-+	struct dentry *dentry;
-+	aufs_bindex_t bdst;
-+	loff_t len;
-+	unsigned int flags;
-+};
-+
-+static void au_call_cpup_simple(void *args)
-+{
-+	struct au_cpup_simple_args *a = args;
-+	*a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
-+}
-+
-+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+		       unsigned int flags)
-+{
-+	int err, wkq_err;
-+	unsigned char do_sio;
-+	struct dentry *parent;
-+	struct inode *h_dir;
-+
-+	parent = dget_parent(dentry);
-+	h_dir = au_h_iptr(parent->d_inode, bdst);
-+	do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
-+	if (!do_sio) {
-+		/*
-+		 * testing CAP_MKNOD is for generic fs,
-+		 * but CAP_FSETID is for xfs only, currently.
-+		 */
-+		umode_t mode = dentry->d_inode->i_mode;
-+		do_sio = (((mode & (S_IFCHR | S_IFBLK))
-+			   && !capable(CAP_MKNOD))
-+			  || ((mode & (S_ISUID | S_ISGID))
-+			      && !capable(CAP_FSETID)));
-+	}
-+	if (!do_sio)
-+		err = au_cpup_simple(dentry, bdst, len, flags);
-+	else {
-+		struct au_cpup_simple_args args = {
-+			.errp		= &err,
-+			.dentry		= dentry,
-+			.bdst		= bdst,
-+			.len		= len,
-+			.flags		= flags
-+		};
-+		wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
-+		if (unlikely(wkq_err))
-+			err = wkq_err;
-+	}
-+
-+	dput(parent);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * copyup the deleted file for writing.
-+ */
-+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
-+			 struct dentry *wh_dentry, struct file *file,
-+			 loff_t len)
-+{
-+	int err;
-+	aufs_bindex_t bstart;
-+	struct au_dinfo *dinfo;
-+	struct dentry *h_d_dst, *h_d_start;
-+
-+	dinfo = au_di(dentry);
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	bstart = dinfo->di_bstart;
-+	h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
-+	dinfo->di_bstart = bdst;
-+	dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
-+	h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
-+	if (file)
-+		dinfo->di_hdentry[0 + bstart].hd_dentry
-+			= au_h_fptr(file, au_fbstart(file))->f_dentry;
-+	err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
-+			     /*h_parent*/NULL);
-+	if (!err && file) {
-+		err = au_reopen_nondir(file);
-+		dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
-+	}
-+	dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
-+	dinfo->di_bstart = bstart;
-+
-+	return err;
-+}
-+
-+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+		      struct file *file)
-+{
-+	int err;
-+	struct au_dtime dt;
-+	struct dentry *parent, *h_parent, *wh_dentry;
-+	struct au_branch *br;
-+	struct path h_path;
-+
-+	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 = br->br_mnt;
-+	au_dtime_store(&dt, parent, &h_path);
-+	err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
-+	if (unlikely(err))
-+		goto out_wh;
-+
-+	dget(wh_dentry);
-+	h_path.dentry = wh_dentry;
-+	if (!S_ISDIR(wh_dentry->d_inode->i_mode))
-+		err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
-+	else
-+		err = vfsub_rmdir(h_parent->d_inode, &h_path);
-+	if (unlikely(err)) {
-+		AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
-+			AuDLNPair(wh_dentry), err);
-+		err = -EIO;
-+	}
-+	au_dtime_revert(&dt);
-+	au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
-+
-+ out_wh:
-+	dput(wh_dentry);
-+ out:
-+	dput(parent);
-+	return err;
-+}
-+
-+struct au_cpup_wh_args {
-+	int *errp;
-+	struct dentry *dentry;
-+	aufs_bindex_t bdst;
-+	loff_t len;
-+	struct file *file;
-+};
-+
-+static void au_call_cpup_wh(void *args)
-+{
-+	struct au_cpup_wh_args *a = args;
-+	*a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
-+}
-+
-+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+		   struct file *file)
-+{
-+	int err, wkq_err;
-+	struct dentry *parent, *h_orph, *h_parent, *h_dentry;
-+	struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
-+	struct au_wbr *wbr;
-+
-+	parent = dget_parent(dentry);
-+	dir = parent->d_inode;
-+	h_orph = NULL;
-+	h_parent = NULL;
-+	h_dir = au_igrab(au_h_iptr(dir, bdst));
-+	h_tmpdir = h_dir;
-+	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 = h_orph->d_inode;
-+		au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
-+
-+		/* this temporary unlock is safe */
-+		if (file)
-+			h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
-+		else
-+			h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
-+		h_inode = h_dentry->d_inode;
-+		IMustLock(h_inode);
-+		mutex_unlock(&h_inode->i_mutex);
-+		mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
-+		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+		/* todo: au_h_open_pre()? */
-+	}
-+
-+	if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
-+		err = au_cpup_wh(dentry, bdst, len, file);
-+	else {
-+		struct au_cpup_wh_args args = {
-+			.errp	= &err,
-+			.dentry	= dentry,
-+			.bdst	= bdst,
-+			.len	= len,
-+			.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);
-+	}
-+	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 dentry *h_parent, void *arg),
-+	       void *arg)
-+{
-+	int err;
-+	struct au_pin pin;
-+	struct dentry *d, *parent, *h_parent, *real_parent;
-+
-+	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 */
-+		if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
-+			if (au_h_dptr(d, bdst))
-+				au_update_dbstart(d);
-+
-+			au_pin_set_dentry(&pin, d);
-+			err = au_do_pin(&pin);
-+			if (!err) {
-+				err = cp(d, bdst, 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 dentry *h_parent __maybe_unused ,
-+		       void *arg __maybe_unused)
-+{
-+	return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
-+}
-+
-+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 = parent->d_inode;
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/cpup.h linux-2.6.33.1/fs/aufs/cpup.h
---- linux-2.6.33.1-vanilla/fs/aufs/cpup.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/cpup.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,81 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * copy-up/down functions
-+ */
-+
-+#ifndef __AUFS_CPUP_H__
-+#define __AUFS_CPUP_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/path.h>
-+#include <linux/time.h>
-+#include <linux/aufs_type.h>
-+
-+struct inode;
-+struct file;
-+
-+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
-+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);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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 au_ftest_cpup(flags, name)	((flags) & AuCpup_##name)
-+#define au_fset_cpup(flags, name)	{ (flags) |= AuCpup_##name; }
-+#define au_fclr_cpup(flags, name)	{ (flags) &= ~AuCpup_##name; }
-+
-+int au_copy_file(struct file *dst, struct file *src, loff_t len);
-+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
-+		       aufs_bindex_t bsrc, loff_t len, unsigned int flags,
-+		       struct dentry *dst_parent);
-+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+		       unsigned int flags);
-+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
-+		   struct file *file);
-+
-+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
-+	       int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
-+			 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 -Nur linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.c linux-2.6.33.1/fs/aufs/dbgaufs.c
---- linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dbgaufs.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,331 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * debugfs interface
-+ */
-+
-+#include <linux/debugfs.h>
-+#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)
-+{
-+	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_vfsmnt, xf->f_dentry, &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);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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 = {
-+	.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_dentry->d_name;
-+	if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
-+		     || memcmp(name->name, DbgaufsXi_PREFIX,
-+			       sizeof(DbgaufsXi_PREFIX) - 1)))
-+		goto out;
-+	err = strict_strtol(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_sbend(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 = {
-+	.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 bend;
-+	struct au_branch *br;
-+	struct au_xino_file *xi;
-+
-+	if (!au_sbi(sb)->si_dbgaufs)
-+		return;
-+
-+	bend = au_sbend(sb);
-+	for (; bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		xi = &br->br_xino;
-+		if (xi->xi_dbgaufs) {
-+			debugfs_remove(xi->xi_dbgaufs);
-+			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 bend;
-+	char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
-+
-+	sbinfo = au_sbi(sb);
-+	parent = sbinfo->si_dbgaufs;
-+	if (!parent)
-+		return;
-+
-+	bend = au_sbend(sb);
-+	for (; bindex <= bend; bindex++) {
-+		snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
-+		br = au_sbr(sb, bindex);
-+		xi = &br->br_xino;
-+		AuDebugOn(xi->xi_dbgaufs);
-+		xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
-+						     sbinfo, &dbgaufs_xino_fop);
-+		/* 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 = {
-+	.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' fucntion 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 '__init' fucntion 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' fucntion 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;
-+
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.h linux-2.6.33.1/fs/aufs/dbgaufs.h
---- linux-2.6.33.1-vanilla/fs/aufs/dbgaufs.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dbgaufs.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,52 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * debugfs interface
-+ */
-+
-+#ifndef __DBGAUFS_H__
-+#define __DBGAUFS_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/init.h>
-+#include <linux/aufs_type.h>
-+
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/dcsub.c linux-2.6.33.1/fs/aufs/dcsub.c
---- linux-2.6.33.1-vanilla/fs/aufs/dcsub.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dcsub.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,223 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sub-routines for dentry cache
-+ */
-+
-+#include "aufs.h"
-+
-+static void au_dpage_free(struct au_dpage *dpage)
-+{
-+	int i;
-+	struct dentry **p;
-+
-+	p = dpage->dentries;
-+	for (i = 0; i < dpage->ndentry; i++)
-+		dput(*p++);
-+	free_page((unsigned long)dpage->dentries);
-+}
-+
-+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
-+{
-+	int err;
-+	void *p;
-+
-+	err = -ENOMEM;
-+	dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
-+	if (unlikely(!dpages->dpages))
-+		goto out;
-+
-+	p = (void *)__get_free_page(gfp);
-+	if (unlikely(!p))
-+		goto out_dpages;
-+
-+	dpages->dpages[0].ndentry = 0;
-+	dpages->dpages[0].dentries = p;
-+	dpages->ndpage = 1;
-+	return 0; /* success */
-+
-+ out_dpages:
-+	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++);
-+	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);
-+		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++;
-+	}
-+
-+	dpage->dentries[dpage->ndentry++] = dget(dentry);
-+	return 0; /* success */
-+
-+ out:
-+	return err;
-+}
-+
-+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
-+		   au_dpages_test test, void *arg)
-+{
-+	int err;
-+	struct dentry *this_parent = root;
-+	struct list_head *next;
-+	struct super_block *sb = root->d_sb;
-+
-+	err = 0;
-+	spin_lock(&dcache_lock);
-+ repeat:
-+	next = this_parent->d_subdirs.next;
-+ resume:
-+	if (this_parent->d_sb == sb
-+	    && !IS_ROOT(this_parent)
-+	    && atomic_read(&this_parent->d_count)
-+	    && this_parent->d_inode
-+	    && (!test || test(this_parent, arg))) {
-+		err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
-+		if (unlikely(err))
-+			goto out;
-+	}
-+
-+	while (next != &this_parent->d_subdirs) {
-+		struct list_head *tmp = next;
-+		struct dentry *dentry = list_entry(tmp, struct dentry,
-+						   d_u.d_child);
-+		next = tmp->next;
-+		if (/*d_unhashed(dentry) || */!dentry->d_inode)
-+			continue;
-+		if (!list_empty(&dentry->d_subdirs)) {
-+			this_parent = dentry;
-+			goto repeat;
-+		}
-+		if (dentry->d_sb == sb
-+		    && atomic_read(&dentry->d_count)
-+		    && (!test || test(dentry, arg))) {
-+			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
-+			if (unlikely(err))
-+				goto out;
-+		}
-+	}
-+
-+	if (this_parent != root) {
-+		next = this_parent->d_u.d_child.next;
-+		this_parent = this_parent->d_parent; /* dcache_lock is locked */
-+		goto resume;
-+	}
-+ out:
-+	spin_unlock(&dcache_lock);
-+	return 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;
-+	spin_lock(&dcache_lock);
-+	if (do_include && (!test || test(dentry, arg))) {
-+		err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
-+		if (unlikely(err))
-+			goto out;
-+	}
-+	while (!IS_ROOT(dentry)) {
-+		dentry = dentry->d_parent; /* dcache_lock is locked */
-+		if (!test || test(dentry, arg)) {
-+			err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
-+			if (unlikely(err))
-+				break;
-+		}
-+	}
-+
-+ out:
-+	spin_unlock(&dcache_lock);
-+
-+	return err;
-+}
-+
-+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
-+{
-+	struct dentry *trap, **dentries;
-+	int err, i, j;
-+	struct au_dcsub_pages dpages;
-+	struct au_dpage *dpage;
-+
-+	trap = ERR_PTR(-ENOMEM);
-+	err = au_dpages_init(&dpages, GFP_NOFS);
-+	if (unlikely(err))
-+		goto out;
-+	err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
-+	if (unlikely(err))
-+		goto out_dpages;
-+
-+	trap = d1;
-+	for (i = 0; !err && i < dpages.ndpage; i++) {
-+		dpage = dpages.dpages + i;
-+		dentries = dpage->dentries;
-+		for (j = 0; !err && j < dpage->ndentry; j++) {
-+			struct dentry *d;
-+
-+			d = dentries[j];
-+			err = (d == d2);
-+			if (!err)
-+				trap = d;
-+		}
-+	}
-+	if (!err)
-+		trap = NULL;
-+
-+ out_dpages:
-+	au_dpages_free(&dpages);
-+ out:
-+	return trap;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dcsub.h linux-2.6.33.1/fs/aufs/dcsub.h
---- linux-2.6.33.1-vanilla/fs/aufs/dcsub.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dcsub.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,54 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sub-routines for dentry cache
-+ */
-+
-+#ifndef __AUFS_DCSUB_H__
-+#define __AUFS_DCSUB_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/types.h>
-+
-+struct dentry;
-+
-+struct au_dpage {
-+	int ndentry;
-+	struct dentry **dentries;
-+};
-+
-+struct au_dcsub_pages {
-+	int ndpage;
-+	struct au_dpage *dpages;
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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);
-+struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_DCSUB_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/debug.c linux-2.6.33.1/fs/aufs/debug.c
---- linux-2.6.33.1-vanilla/fs/aufs/debug.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/debug.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,432 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * debug print functions
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/vt_kern.h>
-+#include "aufs.h"
-+
-+int aufs_debug;
-+MODULE_PARM_DESC(debug, "debug print");
-+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
-+
-+char *au_plevel = KERN_DEBUG;
-+#define dpri(fmt, ...) do { \
-+	if (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 *tpos;
-+	struct hlist_node *pos;
-+
-+	n = whlist->nh_num;
-+	head = whlist->nh_head;
-+	for (ul = 0; ul < n; ul++) {
-+		hlist_for_each_entry(tpos, pos, head, wh_hash)
-+			dpri("b%d, %.*s, %d\n",
-+			     tpos->wh_bindex,
-+			     tpos->wh_str.len, tpos->wh_str.name,
-+			     tpos->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,
-+			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_LSF */
-+	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: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
-+	     " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\n",
-+	     bindex,
-+	     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,
-+	     (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_generation,
-+	     l ? ", wh " : "", l, n);
-+	return 0;
-+}
-+
-+void au_dpri_inode(struct inode *inode)
-+{
-+	struct au_iinfo *iinfo;
-+	aufs_bindex_t bindex;
-+	int err;
-+
-+	err = do_pri_inode(-1, inode, NULL);
-+	if (err || !au_test_aufs(inode->i_sb))
-+		return;
-+
-+	iinfo = au_ii(inode);
-+	if (!iinfo)
-+		return;
-+	dpri("i-1: bstart %d, bend %d, gen %d\n",
-+	     iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
-+	if (iinfo->ii_bstart < 0)
-+		return;
-+	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
-+		do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
-+			     iinfo->ii_hinode[0 + bindex].hi_whdentry);
-+}
-+
-+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
-+{
-+	struct dentry *wh = NULL;
-+
-+	if (!dentry || IS_ERR(dentry)) {
-+		dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
-+		return -1;
-+	}
-+	/* do not call dget_parent() here */
-+	dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
-+	     bindex,
-+	     AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
-+	     dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
-+	     atomic_read(&dentry->d_count), dentry->d_flags);
-+	if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
-+		struct au_iinfo *iinfo = au_ii(dentry->d_inode);
-+		if (iinfo)
-+			wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
-+	}
-+	do_pri_inode(bindex, dentry->d_inode, 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: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
-+	     dinfo->di_bstart, dinfo->di_bend,
-+	     dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
-+	if (dinfo->di_bstart < 0)
-+		return;
-+	for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
-+		do_pri_dentry(bindex, dinfo->di_hdentry[0 + 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
-+	    && file->f_dentry
-+	    && au_test_aufs(file->f_dentry->d_sb)
-+	    && au_fi(file))
-+		snprintf(a, sizeof(a), ", mmapped %d",
-+			 !!au_fi(file)->fi_h_vm_ops);
-+	dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
-+	     bindex, file->f_mode, file->f_flags, (long)file_count(file),
-+	     file->f_pos, a);
-+	if (file->f_dentry)
-+		do_pri_dentry(bindex, file->f_dentry);
-+	return 0;
-+}
-+
-+void au_dpri_file(struct file *file)
-+{
-+	struct au_finfo *finfo;
-+	aufs_bindex_t bindex;
-+	int err;
-+
-+	err = do_pri_file(-1, file);
-+	if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
-+		return;
-+
-+	finfo = au_fi(file);
-+	if (!finfo)
-+		return;
-+	if (finfo->fi_bstart < 0)
-+		return;
-+	for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
-+		struct au_hfile *hf;
-+
-+		hf = finfo->fi_hfile + bindex;
-+		do_pri_file(bindex, hf ? hf->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 = br->br_mnt;
-+	if (!mnt || IS_ERR(mnt))
-+		goto out;
-+	sb = mnt->mnt_sb;
-+	if (!sb || IS_ERR(sb))
-+		goto out;
-+
-+	dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
-+	     "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
-+	     "xino %d\n",
-+	     bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
-+	     au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
-+	     sb->s_flags, sb->s_count - S_BIAS,
-+	     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_perm = 0;
-+	a->fake.br_mnt = &a->mnt;
-+	a->fake.br_xino.xi_file = NULL;
-+	atomic_set(&a->fake.br_count, 0);
-+	smp_mb(); /* atomic_set */
-+	err = do_pri_br(-1, &a->fake);
-+	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_bend; bindex++)
-+		do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_dbg_sleep_jiffy(int jiffy)
-+{
-+	while (jiffy)
-+		jiffy = schedule_timeout_uninterruptible(jiffy);
-+}
-+
-+void au_dbg_iattr(struct iattr *ia)
-+{
-+#define AuBit(name)	if (ia->ia_valid & ATTR_ ## name) \
-+				dpri(#name "\n")
-+	AuBit(MODE);
-+	AuBit(UID);
-+	AuBit(GID);
-+	AuBit(SIZE);
-+	AuBit(ATIME);
-+	AuBit(MTIME);
-+	AuBit(CTIME);
-+	AuBit(ATIME_SET);
-+	AuBit(MTIME_SET);
-+	AuBit(FORCE);
-+	AuBit(ATTR_FLAG);
-+	AuBit(KILL_SUID);
-+	AuBit(KILL_SGID);
-+	AuBit(FILE);
-+	AuBit(KILL_PRIV);
-+	AuBit(OPEN);
-+	AuBit(TIMES_SET);
-+#undef	AuBit
-+	dpri("ia_file %p\n", ia->ia_file);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
-+{
-+	struct dentry *parent;
-+
-+	parent = dget_parent(dentry);
-+	AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
-+		  || IS_ROOT(dentry)
-+		  || au_digen(parent) != sigen);
-+	dput(parent);
-+}
-+
-+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
-+{
-+	struct dentry *parent;
-+
-+	parent = dget_parent(dentry);
-+	AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
-+		  || au_digen(parent) != sigen);
-+	dput(parent);
-+}
-+
-+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(&dpages, parent, /*do_include*/1, NULL, NULL);
-+	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(dentries[j]) != sigen);
-+	}
-+	au_dpages_free(&dpages);
-+}
-+
-+void au_dbg_verify_hf(struct au_finfo *finfo)
-+{
-+	struct au_hfile *hf;
-+	aufs_bindex_t bend, bindex;
-+
-+	if (finfo->fi_bstart >= 0) {
-+		bend = finfo->fi_bend;
-+		for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
-+			hf = finfo->fi_hfile + bindex;
-+			AuDebugOn(hf->hf_file || hf->hf_br);
-+		}
-+	}
-+}
-+
-+void au_dbg_verify_kthread(void)
-+{
-+	if (au_test_wkq(current)) {
-+		au_dbg_blocked();
-+		BUG();
-+	}
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
-+{
-+#ifdef AuForceNoPlink
-+	au_opt_clr(sbinfo->si_mntflags, PLINK);
-+#endif
-+#ifdef AuForceNoXino
-+	au_opt_clr(sbinfo->si_mntflags, XINO);
-+#endif
-+#ifdef AuForceNoRefrof
-+	au_opt_clr(sbinfo->si_mntflags, REFROF);
-+#endif
-+#ifdef AuForceHnotify
-+	au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
-+#endif
-+#ifdef AuForceRd0
-+	sbinfo->si_rdblk = 0;
-+	sbinfo->si_rdhash = 0;
-+#endif
-+}
-+
-+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_warning("CONFIG_4KSTACKS is defined.\n");
-+#endif
-+
-+#ifdef AuForceNoBrs
-+	sysaufs_brs = 0;
-+#endif
-+
-+	return 0;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/debug.h linux-2.6.33.1/fs/aufs/debug.h
---- linux-2.6.33.1-vanilla/fs/aufs/debug.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/debug.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,229 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * debug print functions
-+ */
-+
-+#ifndef __AUFS_DEBUG_H__
-+#define __AUFS_DEBUG_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <asm/system.h>
-+#include <linux/bug.h>
-+/* #include <linux/err.h> */
-+#include <linux/init.h>
-+/* #include <linux/kernel.h> */
-+#include <linux/delay.h>
-+/* #include <linux/kd.h> */
-+/* #include <linux/vt_kern.h> */
-+#include <linux/sysrq.h>
-+#include <linux/aufs_type.h>
-+
-+#include <asm/system.h>
-+
-+#ifdef CONFIG_AUFS_DEBUG
-+#define AuDebugOn(a)		BUG_ON(a)
-+
-+/* module parameter */
-+extern int aufs_debug;
-+static inline void au_debug(int n)
-+{
-+	aufs_debug = n;
-+	smp_mb();
-+}
-+
-+static inline int au_debug_test(void)
-+{
-+	return aufs_debug;
-+}
-+#else
-+#define AuDebugOn(a)		do {} while (0)
-+AuStubVoid(au_debug, int n)
-+AuStubInt0(au_debug_test, void)
-+#endif /* CONFIG_AUFS_DEBUG */
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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_warning(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
-+#define AuDLNPair(d)		AuLNPair(&(d)->d_name)
-+
-+/* ---------------------------------------------------------------------- */
-+
-+struct au_sbinfo;
-+struct au_finfo;
-+struct dentry;
-+#ifdef CONFIG_AUFS_DEBUG
-+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_dentry(struct dentry *dentry);
-+struct file;
-+void au_dpri_file(struct file *filp);
-+struct super_block;
-+void au_dpri_sb(struct super_block *sb);
-+
-+void au_dbg_sleep_jiffy(int jiffy);
-+struct iattr;
-+void au_dbg_iattr(struct iattr *ia);
-+
-+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
-+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
-+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
-+void au_dbg_verify_hf(struct au_finfo *finfo);
-+void au_dbg_verify_kthread(void);
-+
-+int __init au_debug_init(void);
-+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
-+#define AuDbgWhlist(w) do { \
-+	AuDbg(#w "\n"); \
-+	au_dpri_whlist(w); \
-+} while (0)
-+
-+#define AuDbgVdir(v) do { \
-+	AuDbg(#v "\n"); \
-+	au_dpri_vdir(v); \
-+} while (0)
-+
-+#define AuDbgInode(i) do { \
-+	AuDbg(#i "\n"); \
-+	au_dpri_inode(i); \
-+} while (0)
-+
-+#define AuDbgDentry(d) do { \
-+	AuDbg(#d "\n"); \
-+	au_dpri_dentry(d); \
-+} while (0)
-+
-+#define AuDbgFile(f) do { \
-+	AuDbg(#f "\n"); \
-+	au_dpri_file(f); \
-+} while (0)
-+
-+#define AuDbgSb(sb) do { \
-+	AuDbg(#sb "\n"); \
-+	au_dpri_sb(sb); \
-+} while (0)
-+
-+#define AuDbgSleep(sec) do { \
-+	AuDbg("sleep %d sec\n", sec); \
-+	ssleep(sec); \
-+} while (0)
-+
-+#define AuDbgSleepJiffy(jiffy) do { \
-+	AuDbg("sleep %d jiffies\n", jiffy); \
-+	au_dbg_sleep_jiffy(jiffy); \
-+} while (0)
-+
-+#define AuDbgIAttr(ia) do { \
-+	AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
-+	au_dbg_iattr(ia); \
-+} while (0)
-+#else
-+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
-+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
-+	   unsigned int sigen)
-+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
-+AuStubVoid(au_dbg_verify_hf, struct au_finfo *finfo)
-+AuStubVoid(au_dbg_verify_kthread, void)
-+AuStubInt0(__init au_debug_init, void)
-+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
-+
-+#define AuDbgWhlist(w)		do {} while (0)
-+#define AuDbgVdir(v)		do {} while (0)
-+#define AuDbgInode(i)		do {} while (0)
-+#define AuDbgDentry(d)		do {} while (0)
-+#define AuDbgFile(f)		do {} while (0)
-+#define AuDbgSb(sb)		do {} while (0)
-+#define AuDbgSleep(sec)		do {} while (0)
-+#define AuDbgSleepJiffy(jiffy)	do {} while (0)
-+#define AuDbgIAttr(ia)		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', vc_cons[fg_console].d->vc_tty); \
-+} 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 -Nur linux-2.6.33.1-vanilla/fs/aufs/dentry.c linux-2.6.33.1/fs/aufs/dentry.c
---- linux-2.6.33.1-vanilla/fs/aufs/dentry.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dentry.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,874 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * lookup and dentry operations
-+ */
-+
-+#include <linux/namei.h>
-+#include "aufs.h"
-+
-+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
-+{
-+	if (nd) {
-+		*h_nd = *nd;
-+
-+		/*
-+		 * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
-+		 * due to whiteout and branch permission.
-+		 */
-+		h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
-+				 | LOOKUP_FOLLOW);
-+		/* unnecessary? */
-+		h_nd->intent.open.file = NULL;
-+	} else
-+		memset(h_nd, 0, sizeof(*h_nd));
-+}
-+
-+struct au_lkup_one_args {
-+	struct dentry **errp;
-+	struct qstr *name;
-+	struct dentry *h_parent;
-+	struct au_branch *br;
-+	struct nameidata *nd;
-+};
-+
-+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
-+			   struct au_branch *br, struct nameidata *nd)
-+{
-+	struct dentry *h_dentry;
-+	int err;
-+	struct nameidata h_nd;
-+
-+	if (au_test_fs_null_nd(h_parent->d_sb))
-+		return vfsub_lookup_one_len(name->name, h_parent, name->len);
-+
-+	au_h_nd(&h_nd, nd);
-+	h_nd.path.dentry = h_parent;
-+	h_nd.path.mnt = br->br_mnt;
-+
-+	err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
-+	h_dentry = ERR_PTR(err);
-+	if (!err) {
-+		path_get(&h_nd.path);
-+		h_dentry = vfsub_lookup_hash(&h_nd);
-+		path_put(&h_nd.path);
-+	}
-+
-+	AuTraceErrPtr(h_dentry);
-+	return h_dentry;
-+}
-+
-+static void au_call_lkup_one(void *args)
-+{
-+	struct au_lkup_one_args *a = args;
-+	*a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
-+}
-+
-+#define AuLkup_ALLOW_NEG	1
-+#define au_ftest_lkup(flags, name)	((flags) & AuLkup_##name)
-+#define au_fset_lkup(flags, name)	{ (flags) |= AuLkup_##name; }
-+#define au_fclr_lkup(flags, name)	{ (flags) &= ~AuLkup_##name; }
-+
-+struct au_do_lookup_args {
-+	unsigned int		flags;
-+	mode_t			type;
-+	struct nameidata	*nd;
-+};
-+
-+/*
-+ * 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, *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);
-+
-+	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, br, /*try_sio*/0);
-+	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_dbend(dentry, bindex); */
-+	au_set_dbwh(dentry, bindex);
-+	if (!allow_neg)
-+		return NULL; /* success */
-+
-+ real_lookup:
-+	h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
-+	if (IS_ERR(h_dentry))
-+		goto out;
-+
-+	h_inode = h_dentry->d_inode;
-+	if (!h_inode) {
-+		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_dbend(dentry) <= bindex)
-+		au_set_dbend(dentry, bindex);
-+	if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
-+		au_set_dbstart(dentry, bindex);
-+	au_set_h_dptr(dentry, bindex, h_dentry);
-+
-+	inode = dentry->d_inode;
-+	if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
-+	    || (inode && !S_ISDIR(inode->i_mode)))
-+		goto out; /* success */
-+
-+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+	opq = au_diropq_test(h_dentry, br);
-+	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 bstart, mode_t type,
-+		   struct nameidata *nd)
-+{
-+	int npositive, err;
-+	aufs_bindex_t bindex, btail, bdiropq;
-+	unsigned char isdir;
-+	struct qstr whname;
-+	struct au_do_lookup_args args = {
-+		.flags	= 0,
-+		.type	= type,
-+		.nd	= nd
-+	};
-+	const struct qstr *name = &dentry->d_name;
-+	struct dentry *parent;
-+	struct inode *inode;
-+
-+	err = au_test_shwh(dentry->d_sb, name);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_wh_name_alloc(&whname, name);
-+	if (unlikely(err))
-+		goto out;
-+
-+	inode = dentry->d_inode;
-+	isdir = !!(inode && S_ISDIR(inode->i_mode));
-+	if (!type)
-+		au_fset_lkup(args.flags, ALLOW_NEG);
-+
-+	npositive = 0;
-+	parent = dget_parent(dentry);
-+	btail = au_dbtaildir(parent);
-+	for (bindex = bstart; 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 (h_dentry->d_inode)
-+				npositive++;
-+			if (type != S_IFDIR)
-+				break;
-+			continue;
-+		}
-+		h_parent = au_h_dptr(parent, bindex);
-+		if (!h_parent)
-+			continue;
-+		h_dir = h_parent->d_inode;
-+		if (!h_dir || !S_ISDIR(h_dir->i_mode))
-+			continue;
-+
-+		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;
-+		au_fclr_lkup(args.flags, ALLOW_NEG);
-+
-+		if (au_dbwh(dentry) >= 0)
-+			break;
-+		if (!h_dentry)
-+			continue;
-+		h_inode = h_dentry->d_inode;
-+		if (!h_inode)
-+			continue;
-+		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_dbstart(dentry);
-+	}
-+	err = npositive;
-+	if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
-+		     && au_dbstart(dentry) < 0))
-+		/* both of real entry and whiteout found */
-+		err = -EIO;
-+
-+ out_parent:
-+	dput(parent);
-+	kfree(whname.name);
-+ out:
-+	return err;
-+}
-+
-+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
-+			       struct au_branch *br)
-+{
-+	struct dentry *dentry;
-+	int wkq_err;
-+
-+	if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
-+		dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
-+	else {
-+		struct au_lkup_one_args args = {
-+			.errp		= &dentry,
-+			.name		= name,
-+			.h_parent	= parent,
-+			.br		= br,
-+			.nd		= NULL
-+		};
-+
-+		wkq_err = au_wkq_wait(au_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 err;
-+	struct dentry *parent, *h_parent, *h_dentry;
-+
-+	parent = dget_parent(dentry);
-+	h_parent = au_h_dptr(parent, bindex);
-+	h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
-+				   au_sbr(dentry->d_sb, bindex));
-+	err = PTR_ERR(h_dentry);
-+	if (IS_ERR(h_dentry))
-+		goto out;
-+	if (unlikely(h_dentry->d_inode)) {
-+		err = -EIO;
-+		AuIOErr("b%d %.*s should be negative.\n",
-+			bindex, AuDLNPair(h_dentry));
-+		dput(h_dentry);
-+		goto out;
-+	}
-+
-+	err = 0;
-+	if (bindex < au_dbstart(dentry))
-+		au_set_dbstart(dentry, bindex);
-+	if (au_dbend(dentry) < bindex)
-+		au_set_dbend(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; */
-+	uid_t			i_uid;
-+	gid_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 */
-+		|| 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_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 = h_dentry->d_inode;
-+	if (h_inode)
-+		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 = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
-+	err = PTR_ERR(h_d);
-+	if (IS_ERR(h_d))
-+		goto out;
-+
-+	err = 0;
-+	if (unlikely(h_d != h_dentry
-+		     || h_d->d_inode != 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) {
-+		IMustLock(h_dir);
-+		err = (h_dentry->d_parent->d_inode != h_dir);
-+	} else if (udba == AuOpt_UDBA_HNOTIFY)
-+		err = au_h_verify_dentry(h_dentry, h_parent, br);
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
-+				  struct dentry *parent)
-+{
-+	struct dentry *h_d, *h_dp;
-+	struct au_hdentry tmp, *q;
-+	struct super_block *sb;
-+	aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
-+
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	bend = dinfo->di_bend;
-+	bwh = dinfo->di_bwh;
-+	bdiropq = dinfo->di_bdiropq;
-+	for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
-+		h_d = p->hd_dentry;
-+		if (!h_d)
-+			continue;
-+
-+		h_dp = dget_parent(h_d);
-+		if (h_dp == au_h_dptr(parent, bindex)) {
-+			dput(h_dp);
-+			continue;
-+		}
-+
-+		new_bindex = au_find_dbindex(parent, h_dp);
-+		dput(h_dp);
-+		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 = dinfo->di_hdentry + new_bindex;
-+		tmp = *q;
-+		*q = *p;
-+		*p = tmp;
-+		if (tmp.hd_dentry) {
-+			bindex--;
-+			p--;
-+		}
-+	}
-+
-+	sb = parent->d_sb;
-+	dinfo->di_bwh = -1;
-+	if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
-+		dinfo->di_bwh = bwh;
-+
-+	dinfo->di_bdiropq = -1;
-+	if (bdiropq >= 0
-+	    && bdiropq <= au_sbend(sb)
-+	    && au_sbr_whable(sb, bdiropq))
-+		dinfo->di_bdiropq = bdiropq;
-+
-+	bend = au_dbend(parent);
-+	p = dinfo->di_hdentry;
-+	for (bindex = 0; bindex <= bend; bindex++, p++)
-+		if (p->hd_dentry) {
-+			dinfo->di_bstart = bindex;
-+			break;
-+		}
-+
-+	p = dinfo->di_hdentry + bend;
-+	for (bindex = bend; bindex >= 0; bindex--, p--)
-+		if (p->hd_dentry) {
-+			dinfo->di_bend = bindex;
-+			break;
-+		}
-+}
-+
-+/*
-+ * returns the number of found lower positive dentries,
-+ * otherwise an error.
-+ */
-+int au_refresh_hdentry(struct dentry *dentry, mode_t type)
-+{
-+	int npositive, err;
-+	unsigned int sigen;
-+	aufs_bindex_t bstart;
-+	struct au_dinfo *dinfo;
-+	struct super_block *sb;
-+	struct dentry *parent;
-+
-+	DiMustWriteLock(dentry);
-+
-+	sb = dentry->d_sb;
-+	AuDebugOn(IS_ROOT(dentry));
-+	sigen = au_sigen(sb);
-+	parent = dget_parent(dentry);
-+	AuDebugOn(au_digen(parent) != sigen
-+		  || au_iigen(parent->d_inode) != sigen);
-+
-+	dinfo = au_di(dentry);
-+	err = au_di_realloc(dinfo, au_sbend(sb) + 1);
-+	npositive = err;
-+	if (unlikely(err))
-+		goto out;
-+	au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
-+			      parent);
-+
-+	npositive = 0;
-+	bstart = au_dbstart(parent);
-+	if (type != S_IFDIR && dinfo->di_bstart == bstart)
-+		goto out_dgen; /* success */
-+
-+	npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
-+	if (npositive < 0)
-+		goto out;
-+	if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
-+		d_drop(dentry);
-+
-+ out_dgen:
-+	au_update_digen(dentry);
-+ out:
-+	dput(parent);
-+	AuTraceErr(npositive);
-+	return npositive;
-+}
-+
-+static noinline_for_stack
-+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
-+		    struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	int err, valid;
-+	int (*reval)(struct dentry *, struct nameidata *);
-+
-+	err = 0;
-+	reval = NULL;
-+	if (h_dentry->d_op)
-+		reval = h_dentry->d_op->d_revalidate;
-+	if (!reval)
-+		goto out;
-+
-+	AuDbg("b%d\n", bindex);
-+	if (au_test_fs_null_nd(h_dentry->d_sb))
-+		/* it may return tri-state */
-+		valid = reval(h_dentry, NULL);
-+	else {
-+		struct nameidata h_nd;
-+		int locked;
-+		struct dentry *parent;
-+
-+		au_h_nd(&h_nd, nd);
-+		parent = nd->path.dentry;
-+		locked = (nd && nd->path.dentry != dentry);
-+		if (locked)
-+			di_read_lock_parent(parent, AuLock_IR);
-+		BUG_ON(bindex > au_dbend(parent));
-+		h_nd.path.dentry = au_h_dptr(parent, bindex);
-+		BUG_ON(!h_nd.path.dentry);
-+		h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
-+		path_get(&h_nd.path);
-+		valid = reval(h_dentry, &h_nd);
-+		path_put(&h_nd.path);
-+		if (locked)
-+			di_read_unlock(parent, AuLock_IR);
-+	}
-+
-+	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,
-+			  struct nameidata *nd, int do_udba)
-+{
-+	int err;
-+	umode_t mode, h_mode;
-+	aufs_bindex_t bindex, btail, bstart, ibs, ibe;
-+	unsigned char plus, unhashed, is_root, h_plus;
-+	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;
-+
-+	/*
-+	 * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
-+	 * But inotify doesn't fire some necessary events,
-+	 *	IN_ATTRIB for atime/nlink/pageio
-+	 *	IN_DELETE for NFS dentry
-+	 * Let's do REVAL test too.
-+	 */
-+	if (do_udba && inode) {
-+		mode = (inode->i_mode & S_IFMT);
-+		plus = (inode->i_nlink > 0);
-+		ibs = au_ibstart(inode);
-+		ibe = au_ibend(inode);
-+	}
-+
-+	bstart = au_dbstart(dentry);
-+	btail = bstart;
-+	if (inode && S_ISDIR(inode->i_mode))
-+		btail = au_dbtaildir(dentry);
-+	for (bindex = bstart; bindex <= btail; bindex++) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (!h_dentry)
-+			continue;
-+
-+		AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
-+		h_name = &h_dentry->d_name;
-+		if (unlikely(do_udba
-+			     && !is_root
-+			     && (unhashed != !!d_unhashed(h_dentry)
-+				 || name->len != h_name->len
-+				 || memcmp(name->name, h_name->name, name->len))
-+			    )) {
-+			AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
-+				  unhashed, d_unhashed(h_dentry),
-+				  AuDLNPair(dentry), AuDLNPair(h_dentry));
-+			goto err;
-+		}
-+
-+		err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
-+		if (unlikely(err))
-+			/* do not goto err, to keep the errno */
-+			break;
-+
-+		/* todo: plink too? */
-+		if (!do_udba)
-+			continue;
-+
-+		/* UDBA tests */
-+		h_inode = h_dentry->d_inode;
-+		if (unlikely(!!inode != !!h_inode))
-+			goto err;
-+
-+		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 (unlikely(plus != h_plus
-+			     || mode != h_mode
-+			     || h_cached_inode != h_inode))
-+			goto err;
-+		continue;
-+
-+	err:
-+		err = -EINVAL;
-+		break;
-+	}
-+
-+	return err;
-+}
-+
-+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
-+{
-+	int err;
-+	struct dentry *parent;
-+	struct inode *inode;
-+
-+	inode = dentry->d_inode;
-+	if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
-+		return 0;
-+
-+	parent = dget_parent(dentry);
-+	di_read_lock_parent(parent, AuLock_IR);
-+	AuDebugOn(au_digen(parent) != sigen
-+		  || au_iigen(parent->d_inode) != sigen);
-+	au_dbg_verify_gen(parent, sigen);
-+
-+	/* returns a number of positive dentries */
-+	err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
-+	if (err >= 0)
-+		err = au_refresh_hinode(inode, dentry);
-+
-+	di_read_unlock(parent, AuLock_IR);
-+	dput(parent);
-+	return err;
-+}
-+
-+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
-+{
-+	int err;
-+	struct dentry *d, *parent;
-+	struct inode *inode;
-+
-+	if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
-+		return simple_reval_dpath(dentry, sigen);
-+
-+	/* slow loop, keep it simple and stupid */
-+	/* cf: au_cpup_dirs() */
-+	err = 0;
-+	parent = NULL;
-+	while (au_digen(dentry) != sigen
-+	       || au_iigen(dentry->d_inode) != sigen) {
-+		d = dentry;
-+		while (1) {
-+			dput(parent);
-+			parent = dget_parent(d);
-+			if (au_digen(parent) == sigen
-+			    && au_iigen(parent->d_inode) == sigen)
-+				break;
-+			d = parent;
-+		}
-+
-+		inode = d->d_inode;
-+		if (d != dentry)
-+			di_write_lock_child(d);
-+
-+		/* someone might update our dentry while we were sleeping */
-+		if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
-+			di_read_lock_parent(parent, AuLock_IR);
-+			/* returns a number of positive dentries */
-+			err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
-+			if (err >= 0)
-+				err = au_refresh_hinode(inode, d);
-+			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, struct nameidata *nd)
-+{
-+	int valid, err;
-+	unsigned int sigen;
-+	unsigned char do_udba;
-+	struct super_block *sb;
-+	struct inode *inode;
-+
-+	err = -EINVAL;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
-+	sigen = au_sigen(sb);
-+	if (au_digen(dentry) != sigen) {
-+		AuDebugOn(IS_ROOT(dentry));
-+		if (inode)
-+			err = au_reval_dpath(dentry, sigen);
-+		if (unlikely(err))
-+			goto out_dgrade;
-+		AuDebugOn(au_digen(dentry) != sigen);
-+	}
-+	if (inode && au_iigen(inode) != sigen) {
-+		AuDebugOn(IS_ROOT(dentry));
-+		err = au_refresh_hinode(inode, dentry);
-+		if (unlikely(err))
-+			goto out_dgrade;
-+		AuDebugOn(au_iigen(inode) != sigen);
-+	}
-+	di_downgrade_lock(dentry, AuLock_IR);
-+
-+	AuDebugOn(au_digen(dentry) != sigen);
-+	AuDebugOn(inode && au_iigen(inode) != sigen);
-+	err = -EINVAL;
-+	do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
-+	if (do_udba && inode) {
-+		aufs_bindex_t bstart = au_ibstart(inode);
-+
-+		if (bstart >= 0
-+		    && au_test_higen(inode, au_h_iptr(inode, bstart)))
-+			goto out;
-+	}
-+
-+	err = h_d_revalidate(dentry, inode, nd, do_udba);
-+	if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
-+		/* both of real entry and whiteout found */
-+		err = -EIO;
-+	goto out;
-+
-+ out_dgrade:
-+	di_downgrade_lock(dentry, AuLock_IR);
-+ out:
-+	aufs_read_unlock(dentry, AuLock_IR);
-+	AuTraceErr(err);
-+	valid = !err;
-+	if (!valid)
-+		AuDbg("%.*s invalid\n", AuDLNPair(dentry));
-+	return valid;
-+}
-+
-+static void aufs_d_release(struct dentry *dentry)
-+{
-+	struct au_dinfo *dinfo;
-+	aufs_bindex_t bend, bindex;
-+
-+	dinfo = dentry->d_fsdata;
-+	if (!dinfo)
-+		return;
-+
-+	/* dentry may not be revalidated */
-+	bindex = dinfo->di_bstart;
-+	if (bindex >= 0) {
-+		struct au_hdentry *p;
-+
-+		bend = dinfo->di_bend;
-+		p = dinfo->di_hdentry + bindex;
-+		while (bindex++ <= bend) {
-+			if (p->hd_dentry)
-+				au_hdput(p);
-+			p++;
-+		}
-+	}
-+	kfree(dinfo->di_hdentry);
-+	AuRwDestroy(&dinfo->di_rwsem);
-+	au_cache_free_dinfo(dinfo);
-+	au_hn_di_reinit(dentry);
-+}
-+
-+const struct dentry_operations aufs_dop = {
-+	.d_revalidate	= aufs_d_revalidate,
-+	.d_release	= aufs_d_release
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dentry.h linux-2.6.33.1/fs/aufs/dentry.h
---- linux-2.6.33.1-vanilla/fs/aufs/dentry.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dentry.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,228 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * lookup and dentry operations
-+ */
-+
-+#ifndef __AUFS_DENTRY_H__
-+#define __AUFS_DENTRY_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/dcache.h>
-+#include <linux/aufs_type.h>
-+#include "rwsem.h"
-+
-+/* make a single member structure for future use */
-+/* todo: remove this structure */
-+struct au_hdentry {
-+	struct dentry		*hd_dentry;
-+};
-+
-+struct au_dinfo {
-+	atomic_t		di_generation;
-+
-+	struct au_rwsem		di_rwsem;
-+	aufs_bindex_t		di_bstart, di_bend, di_bwh, di_bdiropq;
-+	struct au_hdentry	*di_hdentry;
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* dentry.c */
-+extern const struct dentry_operations aufs_dop;
-+struct au_branch;
-+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
-+			   struct au_branch *br, struct nameidata *nd);
-+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
-+			       struct au_branch *br);
-+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 bstart, mode_t type,
-+		   struct nameidata *nd);
-+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
-+int au_refresh_hdentry(struct dentry *dentry, mode_t type);
-+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
-+
-+/* dinfo.c */
-+int au_alloc_dinfo(struct dentry *dentry);
-+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
-+
-+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);
-+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);
-+void au_update_digen(struct dentry *dentry);
-+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
-+void au_update_dbstart(struct dentry *dentry);
-+void au_update_dbend(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
-+};
-+
-+/*
-+ * 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 void au_hdput(struct au_hdentry *hd)
-+{
-+	dput(hd->hd_dentry);
-+}
-+
-+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
-+{
-+	DiMustAnyLock(dentry);
-+	return au_di(dentry)->di_bstart;
-+}
-+
-+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
-+{
-+	DiMustAnyLock(dentry);
-+	return au_di(dentry)->di_bend;
-+}
-+
-+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_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	DiMustWriteLock(dentry);
-+	au_di(dentry)->di_bstart = bindex;
-+}
-+
-+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	DiMustWriteLock(dentry);
-+	au_di(dentry)->di_bend = bindex;
-+}
-+
-+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	DiMustWriteLock(dentry);
-+	/* dbwh can be outside of bstart - bend 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_return(&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 -Nur linux-2.6.33.1-vanilla/fs/aufs/dinfo.c linux-2.6.33.1/fs/aufs/dinfo.c
---- linux-2.6.33.1-vanilla/fs/aufs/dinfo.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dinfo.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,367 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * dentry private data
-+ */
-+
-+#include "aufs.h"
-+
-+int au_alloc_dinfo(struct dentry *dentry)
-+{
-+	struct au_dinfo *dinfo;
-+	struct super_block *sb;
-+	int nbr;
-+
-+	dinfo = au_cache_alloc_dinfo();
-+	if (unlikely(!dinfo))
-+		goto out;
-+
-+	sb = dentry->d_sb;
-+	nbr = au_sbend(sb) + 1;
-+	if (nbr <= 0)
-+		nbr = 1;
-+	dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
-+	if (unlikely(!dinfo->di_hdentry))
-+		goto out_dinfo;
-+
-+	atomic_set(&dinfo->di_generation, au_sigen(sb));
-+	/* smp_mb(); */ /* atomic_set */
-+	au_rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
-+	dinfo->di_bstart = -1;
-+	dinfo->di_bend = -1;
-+	dinfo->di_bwh = -1;
-+	dinfo->di_bdiropq = -1;
-+
-+	dentry->d_fsdata = dinfo;
-+	dentry->d_op = &aufs_dop;
-+	return 0; /* success */
-+
-+ out_dinfo:
-+	au_cache_free_dinfo(dinfo);
-+ out:
-+	return -ENOMEM;
-+}
-+
-+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
-+{
-+	int err, sz;
-+	struct au_hdentry *hdp;
-+
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	err = -ENOMEM;
-+	sz = sizeof(*hdp) * (dinfo->di_bend + 1);
-+	if (!sz)
-+		sz = sizeof(*hdp);
-+	hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
-+	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)
-+{
-+	au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
-+	if (d->d_inode) {
-+		if (au_ftest_lock(flags, IW))
-+			do_ii_write_lock(d->d_inode, lsc);
-+		else if (au_ftest_lock(flags, IR))
-+			do_ii_read_lock(d->d_inode, lsc);
-+	}
-+}
-+
-+void di_read_unlock(struct dentry *d, int flags)
-+{
-+	if (d->d_inode) {
-+		if (au_ftest_lock(flags, IW))
-+			ii_write_unlock(d->d_inode);
-+		else if (au_ftest_lock(flags, IR))
-+			ii_read_unlock(d->d_inode);
-+	}
-+	au_rw_read_unlock(&au_di(d)->di_rwsem);
-+}
-+
-+void di_downgrade_lock(struct dentry *d, int flags)
-+{
-+	if (d->d_inode && au_ftest_lock(flags, IR))
-+		ii_downgrade_lock(d->d_inode);
-+	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->d_inode)
-+		do_ii_write_lock(d->d_inode, lsc);
-+}
-+
-+void di_write_unlock(struct dentry *d)
-+{
-+	if (d->d_inode)
-+		ii_write_unlock(d->d_inode);
-+	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
-+		  || d1->d_inode == d2->d_inode
-+		  || 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
-+		  || d1->d_inode == d2->d_inode
-+		  || 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 (d1->d_inode == d2->d_inode)
-+		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_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
-+		return NULL;
-+	AuDebugOn(bindex < 0);
-+	d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
-+	AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
-+	return d;
-+}
-+
-+aufs_bindex_t au_dbtail(struct dentry *dentry)
-+{
-+	aufs_bindex_t bend, bwh;
-+
-+	bend = au_dbend(dentry);
-+	if (0 <= bend) {
-+		bwh = au_dbwh(dentry);
-+		if (!bwh)
-+			return bwh;
-+		if (0 < bwh && bwh < bend)
-+			return bwh - 1;
-+	}
-+	return bend;
-+}
-+
-+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
-+{
-+	aufs_bindex_t bend, bopq;
-+
-+	bend = au_dbtail(dentry);
-+	if (0 <= bend) {
-+		bopq = au_dbdiropq(dentry);
-+		if (0 <= bopq && bopq < bend)
-+			bend = bopq;
-+	}
-+	return bend;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
-+		   struct dentry *h_dentry)
-+{
-+	struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
-+
-+	DiMustWriteLock(dentry);
-+
-+	if (hd->hd_dentry)
-+		au_hdput(hd);
-+	hd->hd_dentry = h_dentry;
-+}
-+
-+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;
-+
-+	DiMustWriteLock(dentry);
-+
-+	dinfo = au_di(dentry);
-+	if (!dinfo || dinfo->di_bstart < 0)
-+		return;
-+
-+	if (do_put_zero) {
-+		aufs_bindex_t bindex, bend;
-+
-+		bend = dinfo->di_bend;
-+		for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
-+			h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
-+			if (h_d && !h_d->d_inode)
-+				au_set_h_dptr(dentry, bindex, NULL);
-+		}
-+	}
-+
-+	dinfo->di_bstart = -1;
-+	while (++dinfo->di_bstart <= dinfo->di_bend)
-+		if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
-+			break;
-+	if (dinfo->di_bstart > dinfo->di_bend) {
-+		dinfo->di_bstart = -1;
-+		dinfo->di_bend = -1;
-+		return;
-+	}
-+
-+	dinfo->di_bend++;
-+	while (0 <= --dinfo->di_bend)
-+		if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
-+			break;
-+	AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
-+}
-+
-+void au_update_dbstart(struct dentry *dentry)
-+{
-+	aufs_bindex_t bindex, bend;
-+	struct dentry *h_dentry;
-+
-+	bend = au_dbend(dentry);
-+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (!h_dentry)
-+			continue;
-+		if (h_dentry->d_inode) {
-+			au_set_dbstart(dentry, bindex);
-+			return;
-+		}
-+		au_set_h_dptr(dentry, bindex, NULL);
-+	}
-+}
-+
-+void au_update_dbend(struct dentry *dentry)
-+{
-+	aufs_bindex_t bindex, bstart;
-+	struct dentry *h_dentry;
-+
-+	bstart = au_dbstart(dentry);
-+	for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (!h_dentry)
-+			continue;
-+		if (h_dentry->d_inode) {
-+			au_set_dbend(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, bend;
-+
-+	bend = au_dbend(dentry);
-+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
-+		if (au_h_dptr(dentry, bindex) == h_dentry)
-+			return bindex;
-+	return -1;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dir.c linux-2.6.33.1/fs/aufs/dir.c
---- linux-2.6.33.1-vanilla/fs/aufs/dir.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dir.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,579 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * directory operations
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/fs_stack.h>
-+#include "aufs.h"
-+
-+void au_add_nlink(struct inode *dir, struct inode *h_dir)
-+{
-+	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
-+
-+	dir->i_nlink += h_dir->i_nlink - 2;
-+	if (h_dir->i_nlink < 2)
-+		dir->i_nlink += 2;
-+}
-+
-+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
-+{
-+	AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
-+
-+	dir->i_nlink -= h_dir->i_nlink - 2;
-+	if (h_dir->i_nlink < 2)
-+		dir->i_nlink -= 2;
-+}
-+
-+loff_t au_dir_size(struct file *file, struct dentry *dentry)
-+{
-+	loff_t sz;
-+	aufs_bindex_t bindex, bend;
-+	struct file *h_file;
-+	struct dentry *h_dentry;
-+
-+	sz = 0;
-+	if (file) {
-+		AuDebugOn(!file->f_dentry);
-+		AuDebugOn(!file->f_dentry->d_inode);
-+		AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
-+
-+		bend = au_fbend(file);
-+		for (bindex = au_fbstart(file);
-+		     bindex <= bend && sz < KMALLOC_MAX_SIZE;
-+		     bindex++) {
-+			h_file = au_h_fptr(file, bindex);
-+			if (h_file
-+			    && h_file->f_dentry
-+			    && h_file->f_dentry->d_inode)
-+				sz += i_size_read(h_file->f_dentry->d_inode);
-+		}
-+	} else {
-+		AuDebugOn(!dentry);
-+		AuDebugOn(!dentry->d_inode);
-+		AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
-+
-+		bend = au_dbtaildir(dentry);
-+		for (bindex = au_dbstart(dentry);
-+		     bindex <= bend && sz < KMALLOC_MAX_SIZE;
-+		     bindex++) {
-+			h_dentry = au_h_dptr(dentry, bindex);
-+			if (h_dentry && h_dentry->d_inode)
-+				sz += i_size_read(h_dentry->d_inode);
-+		}
-+	}
-+	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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int reopen_dir(struct file *file)
-+{
-+	int err;
-+	unsigned int flags;
-+	aufs_bindex_t bindex, btail, bstart;
-+	struct dentry *dentry, *h_dentry;
-+	struct file *h_file;
-+
-+	/* open all lower dirs */
-+	dentry = file->f_dentry;
-+	bstart = au_dbstart(dentry);
-+	for (bindex = au_fbstart(file); bindex < bstart; bindex++)
-+		au_set_h_fptr(file, bindex, NULL);
-+	au_set_fbstart(file, bstart);
-+
-+	btail = au_dbtaildir(dentry);
-+	for (bindex = au_fbend(file); btail < bindex; bindex--)
-+		au_set_h_fptr(file, bindex, NULL);
-+	au_set_fbend(file, btail);
-+
-+	flags = vfsub_file_flags(file);
-+	for (bindex = bstart; bindex <= btail; bindex++) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (!h_dentry)
-+			continue;
-+		h_file = au_h_fptr(file, bindex);
-+		if (h_file)
-+			continue;
-+
-+		h_file = au_h_open(dentry, bindex, flags, file);
-+		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)
-+{
-+	int err;
-+	aufs_bindex_t bindex, btail;
-+	struct dentry *dentry, *h_dentry;
-+	struct file *h_file;
-+
-+	FiMustWriteLock(file);
-+
-+	err = 0;
-+	dentry = file->f_dentry;
-+	au_set_fvdir_cache(file, NULL);
-+	file->f_version = dentry->d_inode->i_version;
-+	bindex = au_dbstart(dentry);
-+	au_set_fbstart(file, bindex);
-+	btail = au_dbtaildir(dentry);
-+	au_set_fbend(file, btail);
-+	for (; !err && bindex <= btail; bindex++) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (!h_dentry)
-+			continue;
-+
-+		h_file = au_h_open(dentry, bindex, flags, file);
-+		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_fbstart(file); bindex <= btail; bindex++)
-+		au_set_h_fptr(file, bindex, NULL);
-+	au_set_fbstart(file, -1);
-+	au_set_fbend(file, -1);
-+	return err;
-+}
-+
-+static int aufs_open_dir(struct inode *inode __maybe_unused,
-+			 struct file *file)
-+{
-+	return au_do_open(file, do_open_dir);
-+}
-+
-+static int aufs_release_dir(struct inode *inode __maybe_unused,
-+			    struct file *file)
-+{
-+	struct au_vdir *vdir_cache;
-+	struct super_block *sb;
-+
-+	sb = file->f_dentry->d_sb;
-+	vdir_cache = au_fi(file)->fi_vdir_cache; /* lock-free */
-+	if (vdir_cache)
-+		au_vdir_free(vdir_cache);
-+	au_plink_maint_leave(file);
-+	au_finfo_fin(file);
-+	return 0;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
-+{
-+	int err;
-+	aufs_bindex_t bend, bindex;
-+	struct inode *inode;
-+	struct super_block *sb;
-+
-+	err = 0;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	IMustLock(inode);
-+	bend = au_dbend(dentry);
-+	for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
-+		struct path h_path;
-+		struct inode *h_inode;
-+
-+		if (au_test_ro(sb, bindex, inode))
-+			continue;
-+		h_path.dentry = au_h_dptr(dentry, bindex);
-+		if (!h_path.dentry)
-+			continue;
-+		h_inode = h_path.dentry->d_inode;
-+		if (!h_inode)
-+			continue;
-+
-+		/* no mnt_want_write() */
-+		/* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
-+		/* todo: inotiry fired? */
-+		h_path.mnt = au_sbr_mnt(sb, bindex);
-+		mutex_lock(&h_inode->i_mutex);
-+		err = filemap_fdatawrite(h_inode->i_mapping);
-+		AuDebugOn(!h_inode->i_fop);
-+		if (!err && h_inode->i_fop->fsync)
-+			err = h_inode->i_fop->fsync(NULL, h_path.dentry,
-+						    datasync);
-+		if (!err)
-+			err = filemap_fdatawrite(h_inode->i_mapping);
-+		if (!err)
-+			vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
-+		mutex_unlock(&h_inode->i_mutex);
-+	}
-+
-+	return err;
-+}
-+
-+static int au_do_fsync_dir(struct file *file, int datasync)
-+{
-+	int err;
-+	aufs_bindex_t bend, bindex;
-+	struct file *h_file;
-+	struct super_block *sb;
-+	struct inode *inode;
-+	struct mutex *h_mtx;
-+
-+	err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	sb = file->f_dentry->d_sb;
-+	inode = file->f_dentry->d_inode;
-+	bend = au_fbend(file);
-+	for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
-+		h_file = au_h_fptr(file, bindex);
-+		if (!h_file || au_test_ro(sb, bindex, inode))
-+			continue;
-+
-+		err = vfs_fsync(h_file, h_file->f_dentry, datasync);
-+		if (!err) {
-+			h_mtx = &h_file->f_dentry->d_inode->i_mutex;
-+			mutex_lock(h_mtx);
-+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
-+			/*ignore*/
-+			mutex_unlock(h_mtx);
-+		}
-+	}
-+
-+ out:
-+	return err;
-+}
-+
-+/*
-+ * @file may be NULL
-+ */
-+static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
-+			  int datasync)
-+{
-+	int err;
-+	struct super_block *sb;
-+
-+	IMustLock(dentry->d_inode);
-+
-+	err = 0;
-+	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(dentry->d_inode);
-+	di_write_unlock(dentry);
-+	if (file)
-+		fi_write_unlock(file);
-+
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
-+{
-+	int err;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	inode = dentry->d_inode;
-+	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_vdir_init(file);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	if (!au_test_nfsd(current)) {
-+		err = au_vdir_fill_de(file, dirent, filldir);
-+		fsstack_copy_attr_atime(inode,
-+					au_h_iptr(inode, au_ibstart(inode)));
-+	} else {
-+		/*
-+		 * nfsd filldir may call lookup_one_len(), vfs_getattr(),
-+		 * encode_fh() and others.
-+		 */
-+		struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
-+
-+		di_read_unlock(dentry, AuLock_IR);
-+		si_read_unlock(sb);
-+		/* lockdep_off(); */
-+		err = au_vdir_fill_de(file, dirent, filldir);
-+		/* lockdep_on(); */
-+		fsstack_copy_attr_atime(inode, h_inode);
-+		fi_write_unlock(file);
-+
-+		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)	{ (flags) |= AuTestEmpty_##name; }
-+#define au_fclr_testempty(flags, name)	{ (flags) &= ~AuTestEmpty_##name; }
-+
-+#ifndef CONFIG_AUFS_SHWH
-+#undef AuTestEmpty_SHWH
-+#define AuTestEmpty_SHWH	0
-+#endif
-+
-+struct test_empty_arg {
-+	struct au_nhash *whlist;
-+	unsigned int flags;
-+	int err;
-+	aufs_bindex_t bindex;
-+};
-+
-+static int test_empty_cb(void *__arg, const char *__name, int namelen,
-+			 loff_t offset __maybe_unused, u64 ino,
-+			 unsigned int d_type)
-+{
-+	struct test_empty_arg *arg = __arg;
-+	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);
-+	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)
-+	    && !h_file->f_dentry->d_inode->i_nlink)
-+		goto out_put;
-+
-+	do {
-+		arg->err = 0;
-+		au_fclr_testempty(arg->flags, CALLED);
-+		/* smp_mb(); */
-+		err = vfsub_readdir(h_file, test_empty_cb, arg);
-+		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 = h_dentry->d_inode;
-+	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, bstart, btail;
-+	struct au_nhash whlist;
-+	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;
-+	bstart = au_dbstart(dentry);
-+	if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
-+		au_fset_testempty(arg.flags, SHWH);
-+	arg.bindex = bstart;
-+	err = do_test_empty(dentry, &arg);
-+	if (unlikely(err))
-+		goto out_whlist;
-+
-+	au_fset_testempty(arg.flags, WHONLY);
-+	btail = au_dbtaildir(dentry);
-+	for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
-+		struct dentry *h_dentry;
-+
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (h_dentry && h_dentry->d_inode) {
-+			arg.bindex = bindex;
-+			err = do_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;
-+	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_dbstart(dentry); !err && bindex <= btail; bindex++) {
-+		struct dentry *h_dentry;
-+
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (h_dentry && h_dentry->d_inode) {
-+			arg.bindex = bindex;
-+			err = sio_test_empty(dentry, &arg);
-+		}
-+	}
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+const struct file_operations aufs_dir_fop = {
-+	.read		= generic_read_dir,
-+	.readdir	= aufs_readdir,
-+	.unlocked_ioctl	= aufs_ioctl_dir,
-+	.open		= aufs_open_dir,
-+	.release	= aufs_release_dir,
-+	.flush		= aufs_flush,
-+	.fsync		= aufs_fsync_dir
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/dir.h linux-2.6.33.1/fs/aufs/dir.h
---- linux-2.6.33.1-vanilla/fs/aufs/dir.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/dir.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,127 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * directory operations
-+ */
-+
-+#ifndef __AUFS_DIR_H__
-+#define __AUFS_DIR_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/aufs_type.h>
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* need to be faster and smaller */
-+
-+struct au_nhash {
-+	unsigned int		nh_num;
-+	struct hlist_head	*nh_head;
-+};
-+
-+struct au_vdir_destr {
-+	unsigned char	len;
-+	unsigned char	name[0];
-+} __packed;
-+
-+struct au_vdir_dehstr {
-+	struct hlist_node	hash;
-+	struct au_vdir_destr	*str;
-+};
-+
-+struct 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;
-+	unsigned long	vd_jiffy;
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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);
-+int au_test_empty_lower(struct dentry *dentry);
-+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
-+
-+/* vdir.c */
-+unsigned int au_rdhash_est(loff_t sz);
-+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
-+void au_nhash_wh_free(struct au_nhash *whlist);
-+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
-+			    int limit);
-+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
-+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
-+		       unsigned int d_type, aufs_bindex_t bindex,
-+		       unsigned char shwh);
-+void au_vdir_free(struct au_vdir *vdir);
-+int au_vdir_init(struct file *file);
-+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
-+
-+/* 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);
-+#else
-+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
-+				unsigned long arg)
-+{
-+	return -EINVAL;
-+}
-+#endif
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_DIR_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/export.c linux-2.6.33.1/fs/aufs/export.c
---- linux-2.6.33.1-vanilla/fs/aufs/export.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/export.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,745 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * export via nfs
-+ */
-+
-+#include <linux/exportfs.h>
-+#include <linux/file.h>
-+#include <linux/mnt_namespace.h>
-+#include <linux/namei.h>
-+#include <linux/nsproxy.h>
-+#include <linux/random.h>
-+#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)
-+{
-+	return !!(dentry->d_flags & DCACHE_DISCONNECTED);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+/* inode generation external table */
-+
-+int au_xigen_inc(struct inode *inode)
-+{
-+	int err;
-+	loff_t pos;
-+	ssize_t sz;
-+	__u32 igen;
-+	struct super_block *sb;
-+	struct au_sbinfo *sbinfo;
-+
-+	err = 0;
-+	sb = inode->i_sb;
-+	sbinfo = au_sbi(sb);
-+	/*
-+	 * temporary workaround for escaping from SiMustAnyLock() in
-+	 * au_mntflags(), since this function is called from au_iinfo_fin().
-+	 */
-+	if (unlikely(!au_opt_test(sbinfo->si_mntflags, XINO)))
-+		goto out;
-+
-+	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))
-+		goto out; /* success */
-+
-+	err = sz;
-+	if (unlikely(sz >= 0)) {
-+		err = -EIO;
-+		AuIOErr("xigen error (%zd)\n", sz);
-+	}
-+
-+ out:
-+	return err;
-+}
-+
-+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 (i_size_read(file->f_dentry->d_inode)
-+	    < 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(is_bad_inode(inode)
-+		     || IS_DEADDIR(inode)
-+		     || sigen != au_iigen(inode)))
-+		goto out_iput;
-+
-+	dentry = NULL;
-+	if (!dir_ino || S_ISDIR(inode->i_mode))
-+		dentry = d_find_alias(inode);
-+	else {
-+		spin_lock(&dcache_lock);
-+		list_for_each_entry(d, &inode->i_dentry, d_alias)
-+			if (!au_test_anon(d)
-+			    && d->d_parent->d_inode->i_ino == dir_ino) {
-+				dentry = dget_locked(d);
-+				break;
-+			}
-+		spin_unlock(&dcache_lock);
-+	}
-+	if (unlikely(dentry && sigen != au_digen(dentry))) {
-+		dput(dentry);
-+		dentry = ERR_PTR(-ESTALE);
-+	}
-+
-+ out_iput:
-+	iput(inode);
-+ out:
-+	return dentry;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* todo: dirty? */
-+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
-+static struct vfsmount *au_mnt_get(struct super_block *sb)
-+{
-+	struct mnt_namespace *ns;
-+	struct vfsmount *pos, *mnt;
-+
-+	spin_lock(&vfsmount_lock);
-+	/* no get/put ?? */
-+	AuDebugOn(!current->nsproxy);
-+	ns = current->nsproxy->mnt_ns;
-+	AuDebugOn(!ns);
-+	mnt = NULL;
-+	/* the order (reverse) will not be a problem */
-+	list_for_each_entry(pos, &ns->list, mnt_list)
-+		if (pos->mnt_sb == sb) {
-+			mnt = mntget(pos);
-+			break;
-+		}
-+	spin_unlock(&vfsmount_lock);
-+	AuDebugOn(!mnt);
-+
-+	return mnt;
-+}
-+
-+struct au_nfsd_si_lock {
-+	const unsigned int sigen;
-+	const aufs_bindex_t br_id;
-+	unsigned char force_lock;
-+};
-+
-+static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
-+				       struct au_nfsd_si_lock *nsi_lock)
-+{
-+	aufs_bindex_t bindex;
-+
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	/* branch id may be wrapped around */
-+	bindex = au_br_index(sb, nsi_lock->br_id);
-+	if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
-+		goto out; /* success */
-+
-+	if (!nsi_lock->force_lock)
-+		si_read_unlock(sb);
-+	bindex = -1;
-+
-+ out:
-+	return bindex;
-+}
-+
-+struct find_name_by_ino {
-+	int called, found;
-+	ino_t ino;
-+	char *name;
-+	int namelen;
-+};
-+
-+static int
-+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
-+		 u64 ino, unsigned int d_type)
-+{
-+	struct find_name_by_ino *a = arg;
-+
-+	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;
-+	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 = __getname_gfp(GFP_NOFS);
-+	if (unlikely(!arg.name))
-+		goto out_file;
-+	arg.ino = ino;
-+	arg.found = 0;
-+	do {
-+		arg.called = 0;
-+		/* smp_mb(); */
-+		err = vfsub_readdir(file, find_name_by_ino, &arg);
-+	} while (!err && !arg.found && arg.called);
-+	dentry = ERR_PTR(err);
-+	if (unlikely(err))
-+		goto out_name;
-+	dentry = ERR_PTR(-ENOENT);
-+	if (!arg.found)
-+		goto out_name;
-+
-+	/* do not call au_lkup_one() */
-+	dir = parent->d_inode;
-+	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(!dentry->d_inode)) {
-+		dput(dentry);
-+		dentry = ERR_PTR(-ENOENT);
-+	}
-+
-+ out_name:
-+	__putname(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, aufs_bindex_t bindex,
-+			      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, bindex);
-+	/* au_br_get(br); */
-+	h_mnt = br->br_mnt;
-+	h_sb = h_mnt->mnt_sb;
-+	/* todo: call lower fh_to_dentry()? fh_to_parent()? */
-+	h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
-+				      fh_len - Fh_tail, fh[Fh_h_type],
-+				      h_acceptable, /*context*/NULL);
-+	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, 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(!path.dentry->d_inode))
-+		goto out_path;
-+
-+	if (ino != path.dentry->d_inode->i_ino)
-+		dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
-+	else
-+		dentry = dget(path.dentry);
-+
-+ out_path:
-+	path_put(&path);
-+ out_relock:
-+	if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
-+		if (!IS_ERR(dentry)) {
-+			dput(dentry);
-+			dentry = ERR_PTR(-ESTALE);
-+		}
-+ out_pathname:
-+	free_page((unsigned long)pathname);
-+ out_h_parent:
-+	dput(h_parent);
-+ out:
-+	/* au_br_put(br); */
-+	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;
-+	ino_t ino, dir_ino;
-+	aufs_bindex_t bindex;
-+	struct au_nfsd_si_lock nsi_lock = {
-+		.sigen		= fh[Fh_sigen],
-+		.br_id		= fh[Fh_br_id],
-+		.force_lock	= 0
-+	};
-+
-+	AuDebugOn(fh_len < Fh_tail);
-+
-+	dentry = ERR_PTR(-ESTALE);
-+	/* branch id may be wrapped around */
-+	bindex = si_nfsd_read_lock(sb, &nsi_lock);
-+	if (unlikely(bindex < 0))
-+		goto out;
-+	nsi_lock.force_lock = 1;
-+
-+	/* is this inode still cached? */
-+	ino = decode_ino(fh + Fh_ino);
-+	AuDebugOn(ino == AUFS_ROOT_INO);
-+	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? */
-+	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, bindex, 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 (dentry->d_inode->i_generation == fh[Fh_igen])
-+		goto out_unlock; /* success */
-+
-+	dput(dentry);
-+	dentry = ERR_PTR(-ESTALE);
-+ out_unlock:
-+	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 dentry *dentry, __u32 *fh, int *max_len,
-+			  int connectable)
-+{
-+	int err;
-+	aufs_bindex_t bindex, bend;
-+	struct super_block *sb, *h_sb;
-+	struct inode *inode;
-+	struct dentry *parent, *h_parent;
-+	struct au_branch *br;
-+
-+	AuDebugOn(au_test_anon(dentry));
-+
-+	parent = NULL;
-+	err = -ENOSPC;
-+	if (unlikely(*max_len <= Fh_tail)) {
-+		AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
-+		goto out;
-+	}
-+
-+	err = FILEID_ROOT;
-+	if (IS_ROOT(dentry)) {
-+		AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
-+		goto out;
-+	}
-+
-+	err = -EIO;
-+	h_parent = NULL;
-+	sb = dentry->d_sb;
-+	aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
-+	parent = dget_parent(dentry);
-+	di_read_lock_parent(parent, !AuLock_IR);
-+	inode = dentry->d_inode;
-+	AuDebugOn(!inode);
-+#ifdef CONFIG_AUFS_DEBUG
-+	if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
-+		AuWarn1("NFS-exporting requires xino\n");
-+#endif
-+
-+	bend = au_dbtaildir(parent);
-+	for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
-+		h_parent = au_h_dptr(parent, bindex);
-+		if (h_parent) {
-+			dget(h_parent);
-+			break;
-+		}
-+	}
-+	if (unlikely(!h_parent))
-+		goto out_unlock;
-+
-+	err = -EPERM;
-+	br = au_sbr(sb, bindex);
-+	h_sb = br->br_mnt->mnt_sb;
-+	if (unlikely(!h_sb->s_export_op)) {
-+		AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
-+		goto out_dput;
-+	}
-+
-+	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, parent->d_inode->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 != 255)
-+		err = 99;
-+	else
-+		AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
-+
-+ out_dput:
-+	dput(h_parent);
-+ out_unlock:
-+	di_read_unlock(parent, !AuLock_IR);
-+	dput(parent);
-+	aufs_read_unlock(dentry, AuLock_IR);
-+ out:
-+	if (unlikely(err < 0))
-+		err = 255;
-+	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
-+};
-+
-+void au_export_init(struct super_block *sb)
-+{
-+	struct au_sbinfo *sbinfo;
-+	__u32 u;
-+
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/file.c linux-2.6.33.1/fs/aufs/file.c
---- linux-2.6.33.1-vanilla/fs/aufs/file.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/file.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,606 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * handling file/dir, and address_space operation
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/fsnotify.h>
-+#include <linux/namei.h>
-+#include <linux/pagemap.h>
-+#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)
-+{
-+	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, exec_flag;
-+
-+	/* 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(current) && !h_dentry)
-+		goto out;
-+	h_inode = h_dentry->d_inode;
-+	if (au_test_nfsd(current) && !h_inode)
-+		goto out;
-+	if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
-+		     || !h_inode))
-+		goto out;
-+
-+	sb = dentry->d_sb;
-+	br = au_sbr(sb, bindex);
-+	h_file = ERR_PTR(-EACCES);
-+	exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC);
-+	if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
-+			goto out;
-+
-+	/* drop flags for writing */
-+	if (au_test_ro(sb, bindex, dentry->d_inode))
-+		flags = au_file_roflags(flags);
-+	flags &= ~O_CREAT;
-+	atomic_inc(&br->br_count);
-+	h_path.dentry = h_dentry;
-+	h_path.mnt = br->br_mnt;
-+	if (!au_special_file(h_inode->i_mode))
-+		h_file = vfsub_dentry_open(&h_path, flags);
-+	else {
-+		/* this block depends upon the configuration */
-+		di_read_unlock(dentry, AuLock_IR);
-+		fi_write_unlock(file);
-+		si_read_unlock(sb);
-+		h_file = vfsub_dentry_open(&h_path, flags);
-+		si_noflush_read_lock(sb);
-+		fi_write_lock(file);
-+		di_read_lock_child(dentry, AuLock_IR);
-+	}
-+	if (IS_ERR(h_file))
-+		goto out_br;
-+
-+	if (exec_flag) {
-+		err = deny_write_access(h_file);
-+		if (unlikely(err)) {
-+			fput(h_file);
-+			h_file = ERR_PTR(err);
-+			goto out_br;
-+		}
-+	}
-+	fsnotify_open(h_dentry);
-+	goto out; /* success */
-+
-+ out_br:
-+	atomic_dec(&br->br_count);
-+ out:
-+	return h_file;
-+}
-+
-+int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
-+{
-+	int err;
-+	struct dentry *dentry;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_finfo_init(file);
-+	if (unlikely(err))
-+		goto out;
-+
-+	di_read_lock_child(dentry, AuLock_IR);
-+	err = open(file, vfsub_file_flags(file));
-+	di_read_unlock(dentry, AuLock_IR);
-+
-+	fi_write_unlock(file);
-+	if (unlikely(err))
-+		au_finfo_fin(file);
-+ out:
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+int au_reopen_nondir(struct file *file)
-+{
-+	int err;
-+	aufs_bindex_t bstart, bindex, bend;
-+	struct dentry *dentry;
-+	struct file *h_file, *h_file_tmp;
-+
-+	dentry = file->f_dentry;
-+	AuDebugOn(au_special_file(dentry->d_inode->i_mode));
-+	bstart = au_dbstart(dentry);
-+	h_file_tmp = NULL;
-+	if (au_fbstart(file) == bstart) {
-+		h_file = au_h_fptr(file, bstart);
-+		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, bstart, NULL);
-+	}
-+	AuDebugOn(au_fbstart(file) < bstart
-+		  || au_fi(file)->fi_hfile[0 + bstart].hf_file);
-+
-+	h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
-+			   file);
-+	err = PTR_ERR(h_file);
-+	if (IS_ERR(h_file))
-+		goto out; /* todo: close all? */
-+
-+	err = 0;
-+	au_set_fbstart(file, bstart);
-+	au_set_h_fptr(file, bstart, h_file);
-+	au_update_figen(file);
-+	/* todo: necessary? */
-+	/* file->f_ra = h_file->f_ra; */
-+
-+	/* close lower files */
-+	bend = au_fbend(file);
-+	for (bindex = bstart + 1; bindex <= bend; bindex++)
-+		au_set_h_fptr(file, bindex, NULL);
-+	au_set_fbend(file, bstart);
-+
-+ 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 bstart;
-+	struct au_dinfo *dinfo;
-+	struct dentry *h_dentry;
-+
-+	dinfo = au_di(file->f_dentry);
-+	AuRwMustWriteLock(&dinfo->di_rwsem);
-+
-+	bstart = dinfo->di_bstart;
-+	dinfo->di_bstart = btgt;
-+	h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
-+	dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
-+	err = au_reopen_nondir(file);
-+	dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
-+	dinfo->di_bstart = bstart;
-+
-+	return err;
-+}
-+
-+static int au_ready_to_write_wh(struct file *file, loff_t len,
-+				aufs_bindex_t bcpup)
-+{
-+	int err;
-+	struct inode *inode;
-+	struct dentry *dentry, *hi_wh;
-+
-+	dentry = file->f_dentry;
-+	au_update_dbstart(dentry);
-+	inode = dentry->d_inode;
-+	hi_wh = au_hi_wh(inode, bcpup);
-+	if (!hi_wh)
-+		err = au_sio_cpup_wh(dentry, bcpup, len, file);
-+	else
-+		/* already copied-up after unlink */
-+		err = au_reopen_wh(file, bcpup, hi_wh);
-+
-+	if (!err
-+	    && inode->i_nlink > 1
-+	    && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
-+		au_plink_append(inode, bcpup, au_h_dptr(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 bstart, bcpup;
-+	struct dentry *dentry, *parent, *h_dentry;
-+	struct inode *h_inode, *inode;
-+	struct super_block *sb;
-+	struct file *h_file;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	AuDebugOn(au_special_file(inode->i_mode));
-+	bstart = au_fbstart(file);
-+	err = au_test_ro(sb, bstart, inode);
-+	if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
-+		err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
-+		goto out;
-+	}
-+
-+	/* need to cpup */
-+	parent = dget_parent(dentry);
-+	di_write_lock_parent(parent);
-+	err = AuWbrCopyup(au_sbi(sb), dentry);
-+	bcpup = err;
-+	if (unlikely(err < 0))
-+		goto out_dgrade;
-+	err = 0;
-+
-+	if (!au_h_dptr(parent, bcpup)) {
-+		err = au_cpup_dirs(dentry, bcpup);
-+		if (unlikely(err))
-+			goto out_dgrade;
-+	}
-+
-+	err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
-+		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
-+	if (unlikely(err))
-+		goto out_dgrade;
-+
-+	h_dentry = au_h_fptr(file, bstart)->f_dentry;
-+	h_inode = h_dentry->d_inode;
-+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+	h_file = au_h_open_pre(dentry, bstart);
-+	if (IS_ERR(h_file)) {
-+		err = PTR_ERR(h_file);
-+		h_file = NULL;
-+	} else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
-+	    /* || !h_inode->i_nlink */) {
-+		err = au_ready_to_write_wh(file, len, bcpup);
-+		di_downgrade_lock(parent, AuLock_IR);
-+	} else {
-+		di_downgrade_lock(parent, AuLock_IR);
-+		if (!au_h_dptr(dentry, bcpup))
-+			err = au_sio_cpup_simple(dentry, bcpup, len,
-+						 AuCpup_DTIME);
-+		if (!err)
-+			err = au_reopen_nondir(file);
-+	}
-+	mutex_unlock(&h_inode->i_mutex);
-+	au_h_open_post(dentry, bstart, h_file);
-+
-+	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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
-+{
-+	int err;
-+	aufs_bindex_t bstart;
-+	struct au_pin pin;
-+	struct au_finfo *finfo;
-+	struct dentry *dentry, *parent, *hi_wh;
-+	struct inode *inode;
-+	struct super_block *sb;
-+
-+	FiMustWriteLock(file);
-+
-+	err = 0;
-+	finfo = au_fi(file);
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	bstart = au_ibstart(inode);
-+	if (bstart == finfo->fi_bstart)
-+		goto out;
-+
-+	parent = dget_parent(dentry);
-+	if (au_test_ro(sb, bstart, inode)) {
-+		di_read_lock_parent(parent, !AuLock_IR);
-+		err = AuWbrCopyup(au_sbi(sb), dentry);
-+		bstart = 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, bstart);
-+	if (au_opt_test(au_mntflags(sb), PLINK)
-+	    && au_plink_test(inode)
-+	    && !d_unhashed(dentry)) {
-+		err = au_test_and_cpup_dirs(dentry, bstart);
-+		if (unlikely(err))
-+			goto out_unlock;
-+
-+		/* always superio. */
-+		err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
-+			     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
-+		if (!err)
-+			err = au_sio_cpup_simple(dentry, bstart, -1,
-+						 AuCpup_DTIME);
-+		au_unpin(&pin);
-+	} else if (hi_wh) {
-+		/* already copied-up after unlink */
-+		err = au_reopen_wh(file, bstart, 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_file(struct file *file)
-+{
-+	aufs_bindex_t bindex, bend, new_bindex, brid;
-+	struct au_hfile *p, tmp, *q;
-+	struct au_finfo *finfo;
-+	struct super_block *sb;
-+
-+	FiMustWriteLock(file);
-+
-+	sb = file->f_dentry->d_sb;
-+	finfo = au_fi(file);
-+	p = finfo->fi_hfile + finfo->fi_bstart;
-+	brid = p->hf_br->br_id;
-+	bend = finfo->fi_bend;
-+	for (bindex = finfo->fi_bstart; bindex <= bend; 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 = finfo->fi_hfile + new_bindex;
-+		tmp = *q;
-+		*q = *p;
-+		*p = tmp;
-+		if (tmp.hf_file) {
-+			bindex--;
-+			p--;
-+		}
-+	}
-+
-+	p = finfo->fi_hfile;
-+	if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
-+		bend = au_sbend(sb);
-+		for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
-+		     finfo->fi_bstart++, p++)
-+			if (p->hf_file) {
-+				if (p->hf_file->f_dentry
-+				    && p->hf_file->f_dentry->d_inode)
-+					break;
-+				else
-+					au_hfput(p, file);
-+			}
-+	} else {
-+		bend = au_br_index(sb, brid);
-+		for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
-+		     finfo->fi_bstart++, p++)
-+			if (p->hf_file)
-+				au_hfput(p, file);
-+		bend = au_sbend(sb);
-+	}
-+
-+	p = finfo->fi_hfile + bend;
-+	for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
-+	     finfo->fi_bend--, p--)
-+		if (p->hf_file) {
-+			if (p->hf_file->f_dentry
-+			    && p->hf_file->f_dentry->d_inode)
-+				break;
-+			else
-+				au_hfput(p, file);
-+		}
-+	AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
-+}
-+
-+/*
-+ * after branch manipulating, refresh the file.
-+ */
-+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
-+{
-+	int err, need_reopen;
-+	struct dentry *dentry;
-+	aufs_bindex_t bend, bindex;
-+
-+	dentry = file->f_dentry;
-+	err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
-+	if (unlikely(err))
-+		goto out;
-+	au_do_refresh_file(file);
-+
-+	err = 0;
-+	need_reopen = 1;
-+	if (!au_test_mmapped(file))
-+		err = au_file_refresh_by_inode(file, &need_reopen);
-+	if (!err && need_reopen && !d_unhashed(dentry))
-+		err = reopen(file);
-+	if (!err) {
-+		au_update_figen(file);
-+		return 0; /* success */
-+	}
-+
-+	/* error, close all lower files */
-+	bend = au_fbend(file);
-+	for (bindex = au_fbstart(file); bindex <= bend; 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 bstart;
-+	unsigned char pseudo_link;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+
-+	err = 0;
-+	dentry = file->f_dentry;
-+	inode = dentry->d_inode;
-+	AuDebugOn(au_special_file(inode->i_mode));
-+	sigen = au_sigen(dentry->d_sb);
-+	fi_write_lock(file);
-+	figen = au_figen(file);
-+	di_write_lock_child(dentry);
-+	bstart = au_dbstart(dentry);
-+	pseudo_link = (bstart != au_ibstart(inode));
-+	if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
-+		if (!wlock) {
-+			di_downgrade_lock(dentry, AuLock_IR);
-+			fi_downgrade_lock(file);
-+		}
-+		goto out; /* success */
-+	}
-+
-+	AuDbg("sigen %d, figen %d\n", sigen, figen);
-+	if (sigen != au_digen(dentry)
-+	    || sigen != au_iigen(inode)) {
-+		err = au_reval_dpath(dentry, sigen);
-+		if (unlikely(err < 0))
-+			goto out;
-+		AuDebugOn(au_digen(dentry) != sigen
-+			  || au_iigen(inode) != sigen);
-+	}
-+
-+	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;
-+}
-+
-+/* 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 void aufs_sync_page(struct page *page)
-+{ AuUnsupport(); }
-+
-+static int aufs_set_page_dirty(struct page *page)
-+{ AuUnsupport(); return 0; }
-+static void aufs_invalidatepage(struct page *page, unsigned long offset)
-+{ AuUnsupport(); }
-+static int aufs_releasepage(struct page *page, gfp_t gfp)
-+{ AuUnsupport(); return 0; }
-+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
-+			      const struct iovec *iov, loff_t offset,
-+			      unsigned long nr_segs)
-+{ AuUnsupport(); return 0; }
-+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
-+			    int create, void **kmem, unsigned long *pfn)
-+{ AuUnsupport(); return 0; }
-+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
-+			    struct page *page)
-+{ AuUnsupport(); return 0; }
-+static int aufs_launder_page(struct page *page)
-+{ AuUnsupport(); return 0; }
-+static int aufs_is_partially_uptodate(struct page *page,
-+				      read_descriptor_t *desc,
-+				      unsigned long from)
-+{ AuUnsupport(); return 0; }
-+static int aufs_error_remove_page(struct address_space *mapping,
-+				  struct page *page)
-+{ AuUnsupport(); return 0; }
-+#endif /* CONFIG_AUFS_DEBUG */
-+
-+const struct address_space_operations aufs_aop = {
-+	.readpage		= aufs_readpage,
-+#ifdef CONFIG_AUFS_DEBUG
-+	.writepage		= aufs_writepage,
-+	.sync_page		= aufs_sync_page,
-+	/* 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,
-+	.direct_IO		= aufs_direct_IO,	/* todo */
-+	.get_xip_mem		= aufs_get_xip_mem,	/* todo */
-+	.migratepage		= aufs_migratepage,
-+	.launder_page		= aufs_launder_page,
-+	.is_partially_uptodate	= aufs_is_partially_uptodate,
-+	.error_remove_page	= aufs_error_remove_page
-+#endif /* CONFIG_AUFS_DEBUG */
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/file.h linux-2.6.33.1/fs/aufs/file.h
---- linux-2.6.33.1-vanilla/fs/aufs/file.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/file.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,211 @@
-+/*
-+ * Copyright (C) 2005-2010 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 operations
-+ */
-+
-+#ifndef __AUFS_FILE_H__
-+#define __AUFS_FILE_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/poll.h>
-+#include <linux/aufs_type.h>
-+#include "rwsem.h"
-+
-+struct au_branch;
-+struct au_hfile {
-+	struct file		*hf_file;
-+	struct au_branch	*hf_br;
-+};
-+
-+struct au_vdir;
-+struct au_finfo {
-+	atomic_t		fi_generation;
-+
-+	struct au_rwsem		fi_rwsem;
-+	struct au_hfile		*fi_hfile;
-+	aufs_bindex_t		fi_bstart, fi_bend;
-+
-+	union {
-+		/* non-dir only */
-+		struct {
-+			struct vm_operations_struct	*fi_h_vm_ops;
-+			struct vm_operations_struct	*fi_vm_ops;
-+			struct mutex			fi_vm_mtx;
-+			struct mutex			fi_mmap;
-+		};
-+
-+		/* dir only */
-+		struct {
-+			struct au_vdir		*fi_vdir_cache;
-+		};
-+	};
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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 au_do_open(struct file *file, int (*open)(struct file *file, int flags));
-+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);
-+
-+/* 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);
-+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
-+		    struct file *h_file);
-+#else
-+static inline
-+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	return NULL;
-+}
-+
-+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 aufs_flush(struct file *file, fl_owner_t id);
-+int au_do_open_nondir(struct file *file, int flags);
-+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
-+
-+#ifdef CONFIG_AUFS_SP_IATTR
-+/* f_op_sp.c */
-+int au_special_file(umode_t mode);
-+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
-+#else
-+AuStubInt0(au_special_file, umode_t mode)
-+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
-+				       dev_t rdev)
-+{
-+	init_special_inode(inode, mode, rdev);
-+}
-+#endif
-+
-+/* finfo.c */
-+void au_hfput(struct au_hfile *hf, struct file *file);
-+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
-+		   struct file *h_file);
-+
-+void au_update_figen(struct file *file);
-+void au_fi_mmap_lock(struct file *file);
-+void au_fi_mmap_unlock(struct file *file);
-+
-+void au_finfo_fin(struct file *file);
-+int au_finfo_init(struct file *file);
-+int au_fi_realloc(struct au_finfo *finfo, int nbr);
-+
-+/* ioctl.c */
-+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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_fbstart(struct file *file)
-+{
-+	FiMustAnyLock(file);
-+	return au_fi(file)->fi_bstart;
-+}
-+
-+static inline aufs_bindex_t au_fbend(struct file *file)
-+{
-+	FiMustAnyLock(file);
-+	return au_fi(file)->fi_bend;
-+}
-+
-+static inline struct au_vdir *au_fvdir_cache(struct file *file)
-+{
-+	FiMustAnyLock(file);
-+	return au_fi(file)->fi_vdir_cache;
-+}
-+
-+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
-+{
-+	FiMustWriteLock(file);
-+	au_fi(file)->fi_bstart = bindex;
-+}
-+
-+static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
-+{
-+	FiMustWriteLock(file);
-+	au_fi(file)->fi_bend = bindex;
-+}
-+
-+static inline void au_set_fvdir_cache(struct file *file,
-+				      struct au_vdir *vdir_cache)
-+{
-+	FiMustWriteLock(file);
-+	au_fi(file)->fi_vdir_cache = vdir_cache;
-+}
-+
-+static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
-+{
-+	FiMustAnyLock(file);
-+	return au_fi(file)->fi_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 int au_test_mmapped(struct file *f)
-+{
-+	FiMustAnyLock(f);
-+	return !!(au_fi(f)->fi_h_vm_ops);
-+}
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_FILE_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/finfo.c linux-2.6.33.1/fs/aufs/finfo.c
---- linux-2.6.33.1-vanilla/fs/aufs/finfo.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/finfo.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,146 @@
-+/*
-+ * Copyright (C) 2005-2010 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 private data
-+ */
-+
-+#include <linux/file.h>
-+#include "aufs.h"
-+
-+void au_hfput(struct au_hfile *hf, struct file *file)
-+{
-+	/* todo: direct access f_flags */
-+	if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
-+		allow_write_access(hf->hf_file);
-+	fput(hf->hf_file);
-+	hf->hf_file = NULL;
-+	atomic_dec_return(&hf->hf_br->br_count);
-+	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;
-+
-+	hf = finfo->fi_hfile + bindex;
-+	if (hf->hf_file)
-+		au_hfput(hf, file);
-+	if (val) {
-+		FiMustWriteLock(file);
-+		hf->hf_file = val;
-+		hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
-+	}
-+}
-+
-+void au_update_figen(struct file *file)
-+{
-+	atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
-+	/* smp_mb(); */ /* atomic_set */
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_fi_mmap_lock(struct file *file)
-+{
-+	FiMustWriteLock(file);
-+	lockdep_off();
-+	mutex_lock(&au_fi(file)->fi_mmap);
-+	lockdep_on();
-+}
-+
-+void au_fi_mmap_unlock(struct file *file)
-+{
-+	lockdep_off();
-+	mutex_unlock(&au_fi(file)->fi_mmap);
-+	lockdep_on();
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_finfo_fin(struct file *file)
-+{
-+	struct au_finfo *finfo;
-+	aufs_bindex_t bindex, bend;
-+
-+	finfo = au_fi(file);
-+	bindex = finfo->fi_bstart;
-+	if (bindex >= 0) {
-+		/*
-+		 * calls fput() instead of filp_close(),
-+		 * since no dnotify or lock for the lower file.
-+		 */
-+		bend = finfo->fi_bend;
-+		for (; bindex <= bend; bindex++)
-+			au_set_h_fptr(file, bindex, NULL);
-+	}
-+
-+	au_dbg_verify_hf(finfo);
-+	kfree(finfo->fi_hfile);
-+	AuRwDestroy(&finfo->fi_rwsem);
-+	au_cache_free_finfo(finfo);
-+}
-+
-+int au_finfo_init(struct file *file)
-+{
-+	struct au_finfo *finfo;
-+	struct dentry *dentry;
-+
-+	dentry = file->f_dentry;
-+	finfo = au_cache_alloc_finfo();
-+	if (unlikely(!finfo))
-+		goto out;
-+
-+	finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
-+				  sizeof(*finfo->fi_hfile), GFP_NOFS);
-+	if (unlikely(!finfo->fi_hfile))
-+		goto out_finfo;
-+
-+	au_rw_init_wlock(&finfo->fi_rwsem);
-+	finfo->fi_bstart = -1;
-+	finfo->fi_bend = -1;
-+	atomic_set(&finfo->fi_generation, au_digen(dentry));
-+	/* smp_mb(); */ /* atomic_set */
-+
-+	file->private_data = finfo;
-+	return 0; /* success */
-+
-+ out_finfo:
-+	au_cache_free_finfo(finfo);
-+ out:
-+	return -ENOMEM;
-+}
-+
-+int au_fi_realloc(struct au_finfo *finfo, int nbr)
-+{
-+	int err, sz;
-+	struct au_hfile *hfp;
-+
-+	err = -ENOMEM;
-+	sz = sizeof(*hfp) * (finfo->fi_bend + 1);
-+	if (!sz)
-+		sz = sizeof(*hfp);
-+	hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
-+	if (hfp) {
-+		finfo->fi_hfile = hfp;
-+		err = 0;
-+	}
-+
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/f_op.c linux-2.6.33.1/fs/aufs/f_op.c
---- linux-2.6.33.1-vanilla/fs/aufs/f_op.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/f_op.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,921 @@
-+/*
-+ * Copyright (C) 2005-2010 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 and vm operations
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/fs_stack.h>
-+#include <linux/mman.h>
-+#include <linux/mm.h>
-+#include <linux/security.h>
-+#include "aufs.h"
-+
-+/* common function to regular file and dir */
-+int aufs_flush(struct file *file, fl_owner_t id)
-+{
-+	int err;
-+	aufs_bindex_t bindex, bend;
-+	struct dentry *dentry;
-+	struct file *h_file;
-+
-+	dentry = file->f_dentry;
-+	si_noflush_read_lock(dentry->d_sb);
-+	fi_read_lock(file);
-+	di_read_lock_child(dentry, AuLock_IW);
-+
-+	err = 0;
-+	bend = au_fbend(file);
-+	for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
-+		h_file = au_h_fptr(file, bindex);
-+		if (!h_file || !h_file->f_op || !h_file->f_op->flush)
-+			continue;
-+
-+		err = h_file->f_op->flush(h_file, id);
-+		if (!err)
-+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
-+		/*ignore*/
-+	}
-+	au_cpup_attr_timesizes(dentry->d_inode);
-+
-+	di_read_unlock(dentry, AuLock_IW);
-+	fi_read_unlock(file);
-+	si_read_unlock(dentry->d_sb);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int au_do_open_nondir(struct file *file, int flags)
-+{
-+	int err;
-+	aufs_bindex_t bindex;
-+	struct file *h_file;
-+	struct dentry *dentry;
-+	struct au_finfo *finfo;
-+
-+	FiMustWriteLock(file);
-+
-+	err = 0;
-+	dentry = file->f_dentry;
-+	finfo = au_fi(file);
-+	finfo->fi_h_vm_ops = NULL;
-+	finfo->fi_vm_ops = NULL;
-+	mutex_init(&finfo->fi_mmap); /* regular file only? */
-+	bindex = au_dbstart(dentry);
-+	h_file = au_h_open(dentry, bindex, flags, file);
-+	if (IS_ERR(h_file))
-+		err = PTR_ERR(h_file);
-+	else {
-+		au_set_fbstart(file, bindex);
-+		au_set_fbend(file, bindex);
-+		au_set_h_fptr(file, bindex, h_file);
-+		au_update_figen(file);
-+		/* todo: necessary? */
-+		/* file->f_ra = h_file->f_ra; */
-+	}
-+	return err;
-+}
-+
-+static int aufs_open_nondir(struct inode *inode __maybe_unused,
-+			    struct file *file)
-+{
-+	AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n",
-+	      AuDLNPair(file->f_dentry), vfsub_file_flags(file),
-+	      file->f_mode);
-+	return au_do_open(file, au_do_open_nondir);
-+}
-+
-+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
-+{
-+	kfree(au_fi(file)->fi_vm_ops);
-+	au_finfo_fin(file);
-+	return 0;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
-+			 loff_t *ppos)
-+{
-+	ssize_t err;
-+	struct dentry *dentry;
-+	struct file *h_file;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	err = vfsub_read_u(h_file, buf, count, ppos);
-+	/* todo: necessary? */
-+	/* file->f_ra = h_file->f_ra; */
-+	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_read_unlock(file);
-+ out:
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
-+			  size_t count, loff_t *ppos)
-+{
-+	ssize_t err;
-+	aufs_bindex_t bstart;
-+	struct au_pin pin;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+	struct super_block *sb;
-+	struct file *h_file;
-+	char __user *buf = (char __user *)ubuf;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	mutex_lock(&inode->i_mutex);
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_ready_to_write(file, -1, &pin);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	bstart = au_fbstart(file);
-+	h_file = au_h_fptr(file, bstart);
-+	au_unpin(&pin);
-+	err = vfsub_write_u(h_file, buf, count, ppos);
-+	au_cpup_attr_timesizes(inode);
-+	inode->i_mode = h_file->f_dentry->d_inode->i_mode;
-+
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+ out:
-+	si_read_unlock(sb);
-+	mutex_unlock(&inode->i_mutex);
-+	return err;
-+}
-+
-+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
-+			 const struct iovec *iov, unsigned long nv, loff_t pos)
-+{
-+	ssize_t err;
-+	struct file *file;
-+
-+	err = security_file_permission(h_file, rw);
-+	if (unlikely(err))
-+		goto out;
-+
-+	file = kio->ki_filp;
-+	if (!is_sync_kiocb(kio)) {
-+		get_file(h_file);
-+		fput(file);
-+	}
-+	kio->ki_filp = h_file;
-+	if (rw == MAY_READ)
-+		err = h_file->f_op->aio_read(kio, iov, nv, pos);
-+	else if (rw == MAY_WRITE)
-+		err = h_file->f_op->aio_write(kio, iov, nv, pos);
-+	else
-+		BUG();
-+	/* do not restore kio->ki_filp */
-+
-+ out:
-+	return err;
-+}
-+
-+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
-+			     unsigned long nv, loff_t pos)
-+{
-+	ssize_t err;
-+	struct file *file, *h_file;
-+	struct dentry *dentry;
-+	struct super_block *sb;
-+
-+	file = kio->ki_filp;
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = -ENOSYS;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (h_file->f_op && h_file->f_op->aio_read) {
-+		err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
-+		/* todo: necessary? */
-+		/* file->f_ra = h_file->f_ra; */
-+		fsstack_copy_attr_atime(dentry->d_inode,
-+					h_file->f_dentry->d_inode);
-+	} else
-+		/* currently there is no such fs */
-+		WARN_ON_ONCE(h_file->f_op && h_file->f_op->read);
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_read_unlock(file);
-+
-+ out:
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
-+			      unsigned long nv, loff_t pos)
-+{
-+	ssize_t err;
-+	struct au_pin pin;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+	struct super_block *sb;
-+	struct file *file, *h_file;
-+
-+	file = kio->ki_filp;
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	mutex_lock(&inode->i_mutex);
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_ready_to_write(file, -1, &pin);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	err = -ENOSYS;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	au_unpin(&pin);
-+	if (h_file->f_op && h_file->f_op->aio_write) {
-+		err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
-+		au_cpup_attr_timesizes(inode);
-+		inode->i_mode = h_file->f_dentry->d_inode->i_mode;
-+	} else
-+		/* currently there is no such fs */
-+		WARN_ON_ONCE(h_file->f_op && h_file->f_op->write);
-+
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+ out:
-+	si_read_unlock(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 dentry *dentry;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = -EINVAL;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (au_test_loopback_kthread()) {
-+		file->f_mapping = h_file->f_mapping;
-+		smp_mb(); /* unnecessary? */
-+	}
-+	err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
-+	/* todo: necessasry? */
-+	/* file->f_ra = h_file->f_ra; */
-+	fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_read_unlock(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_pin pin;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+	struct super_block *sb;
-+	struct file *h_file;
-+
-+	dentry = file->f_dentry;
-+	inode = dentry->d_inode;
-+	mutex_lock(&inode->i_mutex);
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_ready_to_write(file, -1, &pin);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	au_unpin(&pin);
-+	err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
-+	au_cpup_attr_timesizes(inode);
-+	inode->i_mode = h_file->f_dentry->d_inode->i_mode;
-+
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+ out:
-+	si_read_unlock(sb);
-+	mutex_unlock(&inode->i_mutex);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static struct file *au_safe_file(struct vm_area_struct *vma)
-+{
-+	struct file *file;
-+
-+	file = vma->vm_file;
-+	if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
-+		return file;
-+	return NULL;
-+}
-+
-+static void au_reset_file(struct vm_area_struct *vma, struct file *file)
-+{
-+	vma->vm_file = file;
-+	/* smp_mb(); */ /* flush vm_file */
-+}
-+
-+static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+	int err;
-+	static DECLARE_WAIT_QUEUE_HEAD(wq);
-+	struct file *file, *h_file;
-+	struct au_finfo *finfo;
-+
-+	/* todo: non-robr mode, user vm_file as it is? */
-+	wait_event(wq, (file = au_safe_file(vma)));
-+
-+	/* do not revalidate, no si lock */
-+	finfo = au_fi(file);
-+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
-+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
-+
-+	mutex_lock(&finfo->fi_vm_mtx);
-+	vma->vm_file = h_file;
-+	err = finfo->fi_h_vm_ops->fault(vma, vmf);
-+	/* todo: necessary? */
-+	/* file->f_ra = h_file->f_ra; */
-+	au_reset_file(vma, file);
-+	mutex_unlock(&finfo->fi_vm_mtx);
-+#if 0 /* def CONFIG_SMP */
-+	/* wake_up_nr(&wq, online_cpu - 1); */
-+	wake_up_all(&wq);
-+#else
-+	wake_up(&wq);
-+#endif
-+
-+	return err;
-+}
-+
-+static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+	int err;
-+	static DECLARE_WAIT_QUEUE_HEAD(wq);
-+	struct file *file, *h_file;
-+	struct au_finfo *finfo;
-+
-+	wait_event(wq, (file = au_safe_file(vma)));
-+
-+	finfo = au_fi(file);
-+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
-+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
-+
-+	mutex_lock(&finfo->fi_vm_mtx);
-+	vma->vm_file = h_file;
-+	err = finfo->fi_h_vm_ops->page_mkwrite(vma, vmf);
-+	au_reset_file(vma, file);
-+	mutex_unlock(&finfo->fi_vm_mtx);
-+	wake_up(&wq);
-+
-+	return err;
-+}
-+
-+static void aufs_vm_close(struct vm_area_struct *vma)
-+{
-+	static DECLARE_WAIT_QUEUE_HEAD(wq);
-+	struct file *file, *h_file;
-+	struct au_finfo *finfo;
-+
-+	wait_event(wq, (file = au_safe_file(vma)));
-+
-+	finfo = au_fi(file);
-+	h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
-+	AuDebugOn(!h_file || !finfo->fi_h_vm_ops);
-+
-+	mutex_lock(&finfo->fi_vm_mtx);
-+	vma->vm_file = h_file;
-+	finfo->fi_h_vm_ops->close(vma);
-+	au_reset_file(vma, file);
-+	mutex_unlock(&finfo->fi_vm_mtx);
-+	wake_up(&wq);
-+}
-+
-+static struct vm_operations_struct aufs_vm_ops = {
-+	/* .close and .page_mkwrite are not set by default */
-+	.fault		= aufs_fault,
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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, EXECUTABLE)
-+		| AuConv_VM_MAP(flags, LOCKED);
-+}
-+
-+static struct vm_operations_struct *au_vm_ops(struct file *h_file,
-+					      struct vm_area_struct *vma)
-+{
-+	struct vm_operations_struct *vm_ops;
-+	unsigned long prot;
-+	int err;
-+
-+	vm_ops = ERR_PTR(-ENODEV);
-+	if (!h_file->f_op || !h_file->f_op->mmap)
-+		goto out;
-+
-+	prot = au_prot_conv(vma->vm_flags);
-+	err = security_file_mmap(h_file, /*reqprot*/prot, prot,
-+				 au_flag_conv(vma->vm_flags), vma->vm_start, 0);
-+	vm_ops = ERR_PTR(err);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = h_file->f_op->mmap(h_file, vma);
-+	vm_ops = ERR_PTR(err);
-+	if (unlikely(err))
-+		goto out;
-+
-+	/* oops, it became 'const' */
-+	vm_ops = (struct vm_operations_struct *)vma->vm_ops;
-+	err = do_munmap(current->mm, vma->vm_start,
-+			vma->vm_end - vma->vm_start);
-+	if (unlikely(err)) {
-+		AuIOErr("failed internal unmapping %.*s, %d\n",
-+			AuDLNPair(h_file->f_dentry), err);
-+		vm_ops = ERR_PTR(-EIO);
-+	}
-+
-+ out:
-+	return vm_ops;
-+}
-+
-+static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
-+{
-+	int err;
-+	struct vm_operations_struct *h_ops;
-+
-+	MtxMustLock(&finfo->fi_mmap);
-+
-+	err = 0;
-+	h_ops = finfo->fi_h_vm_ops;
-+	AuDebugOn(!h_ops);
-+	if ((!h_ops->page_mkwrite && !h_ops->close)
-+	    || finfo->fi_vm_ops)
-+		goto out;
-+
-+	err = -ENOMEM;
-+	finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
-+	if (unlikely(!finfo->fi_vm_ops))
-+		goto out;
-+
-+	err = 0;
-+	if (h_ops->page_mkwrite)
-+		finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
-+	if (h_ops->close)
-+		finfo->fi_vm_ops->close = aufs_vm_close;
-+
-+	vma->vm_ops = finfo->fi_vm_ops;
-+
-+ out:
-+	return err;
-+}
-+
-+/*
-+ * This is another ugly approach to keep the lock order, particularly
-+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
-+ * find it in git-log, if you want.
-+ *
-+ * native readdir: i_mutex, copy_to_user, mmap_sem
-+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
-+ *
-+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
-+ * acquire aufs rwsem. It introduces a circular locking dependency.
-+ * To address this problem, aufs_mmap() delegates the part which requires aufs
-+ * rwsem to its internal workqueue.
-+ */
-+
-+/* very ugly approach */
-+#ifdef CONFIG_DEBUG_MUTEXES
-+#include <../kernel/mutex-debug.h>
-+#else
-+#include <../kernel/mutex.h>
-+#endif
-+
-+struct au_mmap_pre_args {
-+	/* input */
-+	struct file *file;
-+	struct vm_area_struct *vma;
-+
-+	/* output */
-+	int *errp;
-+	struct file *h_file;
-+	int mmapped;
-+};
-+
-+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
-+		       struct file **h_file, int *mmapped)
-+{
-+	int err;
-+	const unsigned char wlock
-+		= !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
-+	struct dentry *dentry;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, !AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	*mmapped = !!au_test_mmapped(file);
-+	if (wlock) {
-+		struct au_pin pin;
-+
-+		err = au_ready_to_write(file, -1, &pin);
-+		di_write_unlock(dentry);
-+		if (unlikely(err))
-+			goto out_unlock;
-+		au_unpin(&pin);
-+	} else
-+		di_write_unlock(dentry);
-+	*h_file = au_h_fptr(file, au_fbstart(file));
-+	get_file(*h_file);
-+	au_fi_mmap_lock(file);
-+
-+out_unlock:
-+	fi_write_unlock(file);
-+out:
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+static void au_call_mmap_pre(void *args)
-+{
-+	struct au_mmap_pre_args *a = args;
-+	*a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->mmapped);
-+}
-+
-+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+	int err, wkq_err;
-+	struct au_finfo *finfo;
-+	struct dentry *h_dentry;
-+	struct vm_operations_struct *vm_ops;
-+	struct au_mmap_pre_args args = {
-+		.file		= file,
-+		.vma		= vma,
-+		.errp		= &err
-+	};
-+
-+	wkq_err = au_wkq_wait(au_call_mmap_pre, &args);
-+	if (unlikely(wkq_err))
-+		err = wkq_err;
-+	if (unlikely(err))
-+		goto out;
-+	finfo = au_fi(file);
-+	mutex_set_owner(&finfo->fi_mmap);
-+
-+	h_dentry = args.h_file->f_dentry;
-+	if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) {
-+		/*
-+		 * by this assignment, f_mapping will differs from aufs inode
-+		 * i_mapping.
-+		 * if someone else mixes the use of f_dentry->d_inode and
-+		 * f_mapping->host, then a problem may arise.
-+		 */
-+		file->f_mapping = args.h_file->f_mapping;
-+	}
-+
-+	vm_ops = NULL;
-+	if (!args.mmapped) {
-+		vm_ops = au_vm_ops(args.h_file, vma);
-+		err = PTR_ERR(vm_ops);
-+		if (IS_ERR(vm_ops))
-+			goto out_unlock;
-+	}
-+
-+	/*
-+	 * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
-+	 * currently MAP_DENYWRITE from userspace is ignored, but elf loader
-+	 * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
-+	 * both of the aufs file and the lower file is deny_write_access()-ed.
-+	 * finally I hope we can skip handlling MAP_DENYWRITE here.
-+	 */
-+	err = generic_file_mmap(file, vma);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	vma->vm_ops = &aufs_vm_ops;
-+	if (!args.mmapped) {
-+		finfo->fi_h_vm_ops = vm_ops;
-+		mutex_init(&finfo->fi_vm_mtx);
-+	}
-+
-+	err = au_custom_vm_ops(finfo, vma);
-+	if (unlikely(err))
-+		goto out_unlock;
-+
-+	vfsub_file_accessed(args.h_file);
-+	/* update without lock, I don't think it a problem */
-+	fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode);
-+
-+ out_unlock:
-+	au_fi_mmap_unlock(file);
-+	fput(args.h_file);
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
-+			     int datasync)
-+{
-+	int err;
-+	struct au_pin pin;
-+	struct inode *inode;
-+	struct file *h_file;
-+	struct super_block *sb;
-+
-+	inode = dentry->d_inode;
-+	IMustLock(file->f_mapping->host);
-+	if (inode != file->f_mapping->host) {
-+		mutex_unlock(&file->f_mapping->host->i_mutex);
-+		mutex_lock(&inode->i_mutex);
-+	}
-+	IMustLock(inode);
-+
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	err = 0; /* -EBADF; */ /* posix? */
-+	if (unlikely(!(file->f_mode & FMODE_WRITE)))
-+		goto out;
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_ready_to_write(file, -1, &pin);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+	au_unpin(&pin);
-+
-+	err = -EINVAL;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (h_file->f_op && h_file->f_op->fsync) {
-+		struct dentry *h_d;
-+		struct mutex *h_mtx;
-+
-+		/*
-+		 * no filemap_fdatawrite() since aufs file has no its own
-+		 * mapping, but dir.
-+		 */
-+		h_d = h_file->f_dentry;
-+		h_mtx = &h_d->d_inode->i_mutex;
-+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+		err = h_file->f_op->fsync(h_file, h_d, datasync);
-+		if (!err)
-+			vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
-+		/*ignore*/
-+		au_cpup_attr_timesizes(inode);
-+		mutex_unlock(h_mtx);
-+	}
-+
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+ out:
-+	si_read_unlock(sb);
-+	if (inode != file->f_mapping->host) {
-+		mutex_unlock(&inode->i_mutex);
-+		mutex_lock(&file->f_mapping->host->i_mutex);
-+	}
-+	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_pin pin;
-+	struct dentry *dentry;
-+	struct inode *inode;
-+	struct file *file, *h_file;
-+	struct super_block *sb;
-+
-+	file = kio->ki_filp;
-+	dentry = file->f_dentry;
-+	inode = dentry->d_inode;
-+	mutex_lock(&inode->i_mutex);
-+
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	err = 0; /* -EBADF; */ /* posix? */
-+	if (unlikely(!(file->f_mode & FMODE_WRITE)))
-+		goto out;
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = au_ready_to_write(file, -1, &pin);
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		goto out_unlock;
-+	au_unpin(&pin);
-+
-+	err = -ENOSYS;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (h_file->f_op && h_file->f_op->aio_fsync) {
-+		struct dentry *h_d;
-+		struct mutex *h_mtx;
-+
-+		h_d = h_file->f_dentry;
-+		h_mtx = &h_d->d_inode->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*/
-+		au_cpup_attr_timesizes(inode);
-+		mutex_unlock(h_mtx);
-+	}
-+
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+ out:
-+	si_read_unlock(sb);
-+	mutex_unlock(&inode->i_mutex);
-+	return err;
-+}
-+#endif
-+
-+static int aufs_fasync(int fd, struct file *file, int flag)
-+{
-+	int err;
-+	struct file *h_file;
-+	struct dentry *dentry;
-+	struct super_block *sb;
-+
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (h_file->f_op && h_file->f_op->fasync)
-+		err = h_file->f_op->fasync(fd, h_file, flag);
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_read_unlock(file);
-+
-+ 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 = {
-+	/*
-+	 * while generic_file_llseek/_unlocked() don't use BKL,
-+	 * don't use it since it operates file->f_mapping->host.
-+	 * in aufs, it may be a real file and may confuse users by UDBA.
-+	 */
-+	/* .llseek		= generic_file_llseek, */
-+
-+	.read		= aufs_read,
-+	.write		= aufs_write,
-+	.aio_read	= aufs_aio_read,
-+	.aio_write	= aufs_aio_write,
-+#ifdef CONFIG_AUFS_POLL
-+	.poll		= aufs_poll,
-+#endif
-+	.unlocked_ioctl	= aufs_ioctl_nondir,
-+	.mmap		= aufs_mmap,
-+	.open		= aufs_open_nondir,
-+	.flush		= aufs_flush,
-+	.release	= aufs_release_nondir,
-+	.fsync		= aufs_fsync_nondir,
-+	/* .aio_fsync	= aufs_aio_fsync_nondir, */
-+	.fasync		= aufs_fasync,
-+	/* .sendpage	= aufs_sendpage, */
-+	.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
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/f_op_sp.c linux-2.6.33.1/fs/aufs/f_op_sp.c
---- linux-2.6.33.1-vanilla/fs/aufs/f_op_sp.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/f_op_sp.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,290 @@
-+/*
-+ * Copyright (C) 2005-2010 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 operations for special files.
-+ * while they exist in aufs virtually,
-+ * their file I/O is handled out of aufs.
-+ */
-+
-+#include <linux/fs_stack.h>
-+#include "aufs.h"
-+
-+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
-+				unsigned long nv, loff_t pos)
-+{
-+	ssize_t err;
-+	aufs_bindex_t bstart;
-+	unsigned char wbr;
-+	struct file *file, *h_file;
-+	struct super_block *sb;
-+
-+	file = kio->ki_filp;
-+	sb = file->f_dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	fi_read_lock(file);
-+	bstart = au_fbstart(file);
-+	h_file = au_h_fptr(file, bstart);
-+	fi_read_unlock(file);
-+	wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
-+	si_read_unlock(sb);
-+
-+	/* do not change the file in kio */
-+	AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
-+	err = h_file->f_op->aio_read(kio, iov, nv, pos);
-+	if (err > 0 && wbr)
-+		file_accessed(h_file);
-+
-+	return err;
-+}
-+
-+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
-+				 unsigned long nv, loff_t pos)
-+{
-+	ssize_t err;
-+	aufs_bindex_t bstart;
-+	unsigned char wbr;
-+	struct super_block *sb;
-+	struct file *file, *h_file;
-+
-+	file = kio->ki_filp;
-+	sb = file->f_dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	fi_read_lock(file);
-+	bstart = au_fbstart(file);
-+	h_file = au_h_fptr(file, bstart);
-+	fi_read_unlock(file);
-+	wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
-+	si_read_unlock(sb);
-+
-+	/* do not change the file in kio */
-+	AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
-+	err = h_file->f_op->aio_write(kio, iov, nv, pos);
-+	if (err > 0 && wbr)
-+		file_update_time(h_file);
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int aufs_release_sp(struct inode *inode, struct file *file)
-+{
-+	int err;
-+	struct file *h_file;
-+
-+	fi_read_lock(file);
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	fi_read_unlock(file);
-+	/* close this fifo in aufs */
-+	err = h_file->f_op->release(inode, file); /* ignore */
-+	aufs_release_nondir(inode, file); /* ignore */
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* currently, support only FIFO */
-+enum {AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
-+      /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
-+      AuSp_Last};
-+static int aufs_open_sp(struct inode *inode, struct file *file);
-+static struct au_sp_fop {
-+	int			done;
-+	struct file_operations	fop;	/* not 'const' */
-+	spinlock_t		spin;
-+} au_sp_fop[AuSp_Last] = {
-+	[AuSp_FIFO] = {
-+		.fop	= {
-+			.open	= aufs_open_sp
-+		}
-+	}
-+};
-+
-+static void au_init_fop_sp(struct file *file)
-+{
-+	struct au_sp_fop *p;
-+	int i;
-+	struct file *h_file;
-+
-+	p = au_sp_fop;
-+	if (unlikely(!p->done)) {
-+		/* initialize first time only */
-+		static DEFINE_SPINLOCK(spin);
-+
-+		spin_lock(&spin);
-+		if (!p->done) {
-+			BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
-+				     != AuSp_Last);
-+			for (i = 0; i < AuSp_Last; i++)
-+				spin_lock_init(&p[i].spin);
-+			p->done = 1;
-+		}
-+		spin_unlock(&spin);
-+	}
-+
-+	switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
-+	case FMODE_READ:
-+		i = AuSp_FIFO_R;
-+		break;
-+	case FMODE_WRITE:
-+		i = AuSp_FIFO_W;
-+		break;
-+	case FMODE_READ | FMODE_WRITE:
-+		i = AuSp_FIFO_RW;
-+		break;
-+	default:
-+		BUG();
-+	}
-+
-+	p += i;
-+	if (unlikely(!p->done)) {
-+		/* initialize first time only */
-+		h_file = au_h_fptr(file, au_fbstart(file));
-+		spin_lock(&p->spin);
-+		if (!p->done) {
-+			p->fop = *h_file->f_op;
-+			if (p->fop.aio_read)
-+				p->fop.aio_read = aufs_aio_read_sp;
-+			if (p->fop.aio_write)
-+				p->fop.aio_write = aufs_aio_write_sp;
-+			p->fop.release = aufs_release_sp;
-+			p->done = 1;
-+		}
-+		spin_unlock(&p->spin);
-+	}
-+	file->f_op = &p->fop;
-+}
-+
-+static int au_cpup_sp(struct dentry *dentry)
-+{
-+	int err;
-+	aufs_bindex_t bcpup;
-+	struct au_pin pin;
-+	struct au_wr_dir_args wr_dir_args = {
-+		.force_btgt	= -1,
-+		.flags		= 0
-+	};
-+
-+	AuDbg("%.*s\n", AuDLNPair(dentry));
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	di_write_lock_child(dentry);
-+	err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
-+	if (unlikely(err < 0))
-+		goto out;
-+	bcpup = err;
-+	err = 0;
-+	if (bcpup == au_dbstart(dentry))
-+		goto out; /* success */
-+
-+	err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
-+		     AuPin_MNT_WRITE);
-+	if (!err) {
-+		err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
-+		au_unpin(&pin);
-+	}
-+
-+ out:
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	return err;
-+}
-+
-+static int au_do_open_sp(struct file *file, int flags)
-+{
-+	int err;
-+	struct dentry *dentry;
-+	struct super_block *sb;
-+	struct file *h_file;
-+	struct inode *h_inode;
-+
-+	dentry = file->f_dentry;
-+	AuDbg("%.*s\n", AuDLNPair(dentry));
-+
-+	/*
-+	 * try copying-up.
-+	 * operate on the ro branch is not an error.
-+	 */
-+	au_cpup_sp(dentry); /* ignore */
-+
-+	/* prepare h_file */
-+	err = au_do_open_nondir(file, vfsub_file_flags(file));
-+	if (unlikely(err))
-+		goto out;
-+
-+	sb = dentry->d_sb;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	h_inode = h_file->f_dentry->d_inode;
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_write_unlock(file);
-+	si_read_unlock(sb);
-+	/* open this fifo in aufs */
-+	err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
-+	si_noflush_read_lock(sb);
-+	fi_write_lock(file);
-+	di_read_lock_child(dentry, AuLock_IR);
-+	if (!err)
-+		au_init_fop_sp(file);
-+	else
-+		au_finfo_fin(file);
-+
-+ out:
-+	return err;
-+}
-+
-+static int aufs_open_sp(struct inode *inode, struct file *file)
-+{
-+	return au_do_open(file, au_do_open_sp);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
-+{
-+	init_special_inode(inode, mode, rdev);
-+
-+	switch (mode & S_IFMT) {
-+	case S_IFIFO:
-+		inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
-+		/*FALLTHROUGH*/
-+	case S_IFCHR:
-+	case S_IFBLK:
-+	case S_IFSOCK:
-+		break;
-+	default:
-+		AuDebugOn(1);
-+	}
-+}
-+
-+int au_special_file(umode_t mode)
-+{
-+	int ret;
-+
-+	ret = 0;
-+	switch (mode & S_IFMT) {
-+	case S_IFIFO:
-+#if 0
-+	case S_IFCHR:
-+	case S_IFBLK:
-+	case S_IFSOCK:
-+#endif
-+		ret = 1;
-+	}
-+
-+	return ret;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/fstype.h linux-2.6.33.1/fs/aufs/fstype.h
---- linux-2.6.33.1-vanilla/fs/aufs/fstype.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/fstype.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,497 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * judging filesystem type
-+ */
-+
-+#ifndef __AUFS_FSTYPE_H__
-+#define __AUFS_FSTYPE_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/magic.h>
-+#include <linux/romfs_fs.h>
-+#include <linux/aufs_type.h>
-+
-+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 defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
-+	return sb->s_magic == ROMFS_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
-+	return sb->s_magic == ISOFS_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
-+	return sb->s_magic == CRAMFS_MAGIC;
-+#endif
-+	return 0;
-+}
-+
-+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
-+	return sb->s_magic == NFS_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
-+	return sb->s_magic == FUSE_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
-+	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 defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
-+	return !strcmp(au_sbtype(sb), "ecryptfs");
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
-+	return sb->s_magic == SMB_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
-+	return sb->s_magic == OCFS2_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
-+	return sb->s_magic == DLMFS_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_coda(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
-+	return sb->s_magic == CODA_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
-+	return sb->s_magic == V9FS_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
-+	return sb->s_magic == EXT4_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
-+	return !strcmp(au_sbtype(sb), "sysv");
-+#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 defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
-+	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 defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
-+	return sb->s_magic == CONFIGFS_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_minix(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
-+	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_cifs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
-+	return sb->s_magic == CIFS_MAGIC_NUMBER;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_fat(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
-+	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 defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
-+	return sb->s_magic == SQUASHFS_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
-+	return sb->s_magic == BTRFS_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
-+	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 defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
-+	return sb->s_magic == NILFS_SUPER_MAGIC;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
-+{
-+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
-+	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 */
-+}
-+
-+/*
-+ * If the filesystem supports NFS-export, then it has to support NULL as
-+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
-+ * We can apply this principle when we handle a lower filesystem.
-+ */
-+static inline int au_test_fs_null_nd(struct super_block *sb)
-+{
-+	return !!sb->s_export_op;
-+}
-+
-+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_smbfs(sb) */	/* untested */
-+		/* || au_test_ocfs2(sb) */	/* untested */
-+		/* || au_test_btrfs(sb) */	/* untested */
-+		/* || au_test_coda(sb) */	/* untested */
-+		/* || au_test_v9fs(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_ext4(sb) */	/* untested */
-+		/* || au_test_ocfs2(sb) */	/* untested */
-+		/* || au_test_ocfs2_dlmfs(sb) */ /* untested */
-+		/* || au_test_sysv(sb) */	/* untested */
-+		/* || 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_cifs(sb) */	/* untested */
-+		|| 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_btrfs(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)
-+		/* || au_test_cifs(sb) */	/* untested */
-+		;
-+}
-+
-+/*
-+ * filesystems which requires replacing i_mapping.
-+ */
-+static inline int au_test_fs_bad_mapping(struct super_block *sb)
-+{
-+	return 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)
-+#ifdef CONFIG_AUFS_BR_RAMFS
-+		|| !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
-+#else
-+		|| !au_test_fs_null_nd(sb) /* to keep xino code simple */
-+#endif
-+		/* 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);
-+}
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_FSTYPE_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hfsnotify.c \
                linux-2.6.33.1/fs/aufs/hfsnotify.c
---- linux-2.6.33.1-vanilla/fs/aufs/hfsnotify.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/hfsnotify.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,230 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 struct fsnotify_group *au_hfsn_group;
-+
-+static void au_hfsn_free_mark(struct fsnotify_mark_entry *entry)
-+{
-+#if 0
-+	struct au_hnotify *hn = container_of(entry, struct au_hnotify,
-+					     hn_entry);
-+	au_cache_free_hnotify(hn);
-+#endif
-+	AuDbg("here\n");
-+}
-+
-+static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode)
-+{
-+	struct fsnotify_mark_entry *entry;
-+
-+	entry = &hn->hn_entry;
-+	fsnotify_init_mark(entry, au_hfsn_free_mark);
-+	entry->mask = AuHfsnMask;
-+	return fsnotify_add_mark(entry, au_hfsn_group, h_inode);
-+}
-+
-+static void au_hfsn_free(struct au_hnotify *hn)
-+{
-+	struct fsnotify_mark_entry *entry;
-+
-+	entry = &hn->hn_entry;
-+	fsnotify_destroy_mark_by_entry(entry);
-+	fsnotify_put_mark(entry);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
-+{
-+	struct fsnotify_mark_entry *entry;
-+
-+	entry = &hinode->hi_notify->hn_entry;
-+	spin_lock(&entry->lock);
-+	if (do_set) {
-+		AuDebugOn(entry->mask & AuHfsnMask);
-+		entry->mask |= AuHfsnMask;
-+	} else {
-+		AuDebugOn(!(entry->mask & AuHfsnMask));
-+		entry->mask &= ~AuHfsnMask;
-+	}
-+	spin_unlock(&entry->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)	if (mask & flag) \
-+				return #flag;
-+	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_IN_ISDIR);
-+	test_ret(FS_IN_ONESHOT);
-+	test_ret(FS_EVENT_ON_CHILD);
-+	return "";
-+#undef test_ret
-+#else
-+	return "??";
-+#endif
-+}
-+#endif
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_hfsn_handle_event(struct fsnotify_group *group,
-+				struct fsnotify_event *event)
-+{
-+	int err;
-+	struct au_hnotify *hnotify;
-+	struct inode *h_dir, *h_inode;
-+	__u32 mask;
-+	struct fsnotify_mark_entry *entry;
-+	struct qstr h_child_qstr = {
-+		.name	= event->file_name,
-+		.len	= event->name_len
-+	};
-+
-+	AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
-+
-+	err = 0;
-+	/* if IN_UNMOUNT happens, there must be another bug */
-+	mask = event->mask;
-+	AuDebugOn(mask & FS_UNMOUNT);
-+	if (mask & (IN_IGNORED | IN_UNMOUNT))
-+		goto out;
-+
-+	h_dir = event->to_tell;
-+	h_inode = event->inode;
-+#ifdef AuDbgHnotify
-+	au_debug(1);
-+	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(0);
-+#endif
-+
-+	spin_lock(&h_dir->i_lock);
-+	entry = fsnotify_find_mark_entry(group, h_dir);
-+	spin_unlock(&h_dir->i_lock);
-+	if (entry) {
-+		hnotify = container_of(entry, struct au_hnotify, hn_entry);
-+		err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
-+		fsnotify_put_mark(entry);
-+	}
-+
-+out:
-+	return err;
-+}
-+
-+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
-+/* it should be exported to modules */
-+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
-+				      struct inode *h_inode, __u32 mask)
-+{
-+	struct fsnotify_mark_entry *entry;
-+	bool send;
-+
-+	spin_lock(&h_inode->i_lock);
-+	entry = fsnotify_find_mark_entry(group, h_inode);
-+	spin_unlock(&h_inode->i_lock);
-+	if (!entry)
-+		return false;
-+
-+	mask = (mask & ~FS_EVENT_ON_CHILD);
-+	send = (entry->mask & mask);
-+
-+	/* find took a reference */
-+	fsnotify_put_mark(entry);
-+
-+	return send;
-+}
-+
-+static struct fsnotify_ops au_hfsn_ops = {
-+	.should_send_event	= au_hfsn_should_send_event,
-+	.handle_event		= au_hfsn_handle_event
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int __init au_hfsn_init(void)
-+{
-+	int err;
-+	unsigned int gn;
-+	const unsigned int gn_max = 10;
-+
-+	gn = 0;
-+	for (gn = 0; gn < gn_max; gn++) {
-+		au_hfsn_group = fsnotify_obtain_group(gn, AuHfsnMask,
-+						      &au_hfsn_ops);
-+		if (au_hfsn_group != ERR_PTR(-EEXIST))
-+			break;
-+	}
-+
-+	err = 0;
-+	if (IS_ERR(au_hfsn_group)) {
-+		pr_err("fsnotify_obtain_group() failed %u times\n", gn_max);
-+		err = PTR_ERR(au_hfsn_group);
-+	}
-+
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+static void au_hfsn_fin(void)
-+{
-+	fsnotify_put_group(au_hfsn_group);
-+}
-+
-+const struct au_hnotify_op au_hnotify_op = {
-+	.ctl		= au_hfsn_ctl,
-+	.alloc		= au_hfsn_alloc,
-+	.free		= au_hfsn_free,
-+
-+	.fin		= au_hfsn_fin,
-+	.init		= au_hfsn_init
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hfsplus.c linux-2.6.33.1/fs/aufs/hfsplus.c
---- linux-2.6.33.1-vanilla/fs/aufs/hfsplus.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/hfsplus.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright (C) 2010 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
-+ */
-+
-+/*
-+ * 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 <linux/file.h>
-+#include "aufs.h"
-+
-+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
-+{
-+	struct file *h_file;
-+	struct dentry *h_dentry;
-+
-+	h_dentry = au_h_dptr(dentry, bindex);
-+	AuDebugOn(!h_dentry);
-+	AuDebugOn(!h_dentry->d_inode);
-+	IMustLock(h_dentry->d_inode);
-+
-+	h_file = NULL;
-+	if (au_test_hfsplus(h_dentry->d_sb)
-+	    && S_ISREG(h_dentry->d_inode->i_mode))
-+		h_file = au_h_open(dentry, bindex,
-+				   O_RDONLY | O_NOATIME | O_LARGEFILE,
-+				   /*file*/NULL);
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/hinotify.c \
                linux-2.6.33.1/fs/aufs/hinotify.c
---- linux-2.6.33.1-vanilla/fs/aufs/hinotify.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/hinotify.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,227 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * inotify for the lower directories (deprecated)
-+ */
-+
-+#include "aufs.h"
-+
-+static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
-+static struct inotify_handle *au_hin_handle;
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_hin_alloc(struct au_hnotify *hn, struct inode *h_inode)
-+{
-+	int err;
-+	s32 wd;
-+	struct inotify_watch *watch;
-+
-+	err = -EEXIST;
-+	wd = inotify_find_watch(au_hin_handle, h_inode, &watch);
-+	if (wd >= 0) {
-+		put_inotify_watch(watch);
-+		goto out;
-+	}
-+
-+	err = 0;
-+	inotify_init_watch(&hn->hn_watch);
-+	wd = inotify_add_watch(au_hin_handle, &hn->hn_watch, h_inode,
-+			       AuHinMask);
-+	if (unlikely(wd < 0)) {
-+		err = wd;
-+		put_inotify_watch(&hn->hn_watch);
-+	}
-+
-+out:
-+	return err;
-+}
-+
-+static void au_hin_free(struct au_hnotify *hn)
-+{
-+	int err;
-+
-+	err = 0;
-+	if (atomic_read(&hn->hn_watch.count))
-+		err = inotify_rm_watch(au_hin_handle, &hn->hn_watch);
-+	if (unlikely(err))
-+		/* it means the watch is already removed */
-+		pr_warning("failed inotify_rm_watch() %d\n", err);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void au_hin_ctl(struct au_hinode *hinode, int do_set)
-+{
-+	struct inode *h_inode;
-+	struct inotify_watch *watch;
-+
-+	h_inode = hinode->hi_inode;
-+	IMustLock(h_inode);
-+
-+	/* todo: try inotify_find_update_watch()? */
-+	watch = &hinode->hi_notify->hn_watch;
-+	mutex_lock(&h_inode->inotify_mutex);
-+	/* mutex_lock(&watch->ih->mutex); */
-+	if (do_set) {
-+		AuDebugOn(watch->mask & AuHinMask);
-+		watch->mask |= AuHinMask;
-+	} else {
-+		AuDebugOn(!(watch->mask & AuHinMask));
-+		watch->mask &= ~AuHinMask;
-+	}
-+	/* mutex_unlock(&watch->ih->mutex); */
-+	mutex_unlock(&h_inode->inotify_mutex);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+#ifdef AuDbgHnotify
-+static char *in_name(u32 mask)
-+{
-+#ifdef CONFIG_AUFS_DEBUG
-+#define test_ret(flag)	if (mask & flag) \
-+				return #flag;
-+	test_ret(IN_ACCESS);
-+	test_ret(IN_MODIFY);
-+	test_ret(IN_ATTRIB);
-+	test_ret(IN_CLOSE_WRITE);
-+	test_ret(IN_CLOSE_NOWRITE);
-+	test_ret(IN_OPEN);
-+	test_ret(IN_MOVED_FROM);
-+	test_ret(IN_MOVED_TO);
-+	test_ret(IN_CREATE);
-+	test_ret(IN_DELETE);
-+	test_ret(IN_DELETE_SELF);
-+	test_ret(IN_MOVE_SELF);
-+	test_ret(IN_UNMOUNT);
-+	test_ret(IN_Q_OVERFLOW);
-+	test_ret(IN_IGNORED);
-+	return "";
-+#undef test_ret
-+#else
-+	return "??";
-+#endif
-+}
-+#endif
-+
-+static u32 au_hin_conv_mask(u32 mask)
-+{
-+	u32 conv;
-+
-+	conv = 0;
-+#define do_conv(flag)	conv |= (mask & IN_ ## flag) ? FS_ ## flag : 0
-+	do_conv(ACCESS);
-+	do_conv(MODIFY);
-+	do_conv(ATTRIB);
-+	do_conv(CLOSE_WRITE);
-+	do_conv(CLOSE_NOWRITE);
-+	do_conv(OPEN);
-+	do_conv(MOVED_FROM);
-+	do_conv(MOVED_TO);
-+	do_conv(CREATE);
-+	do_conv(DELETE);
-+	do_conv(DELETE_SELF);
-+	do_conv(MOVE_SELF);
-+	do_conv(UNMOUNT);
-+	do_conv(Q_OVERFLOW);
-+#undef do_conv
-+#define do_conv(flag)	conv |= (mask & IN_ ## flag) ? FS_IN_ ## flag : 0
-+	do_conv(IGNORED);
-+	/* do_conv(ISDIR); */
-+	/* do_conv(ONESHOT); */
-+#undef do_conv
-+
-+	return conv;
-+}
-+
-+static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
-+			 u32 mask, u32 cookie __maybe_unused,
-+			 const char *h_child_name, struct inode *h_child_inode)
-+{
-+	struct au_hnotify *hnotify;
-+	struct qstr h_child_qstr = {
-+		.name = h_child_name
-+	};
-+
-+	/* if IN_UNMOUNT happens, there must be another bug */
-+	AuDebugOn(mask & IN_UNMOUNT);
-+	if (mask & (IN_IGNORED | IN_UNMOUNT)) {
-+		put_inotify_watch(watch);
-+		return;
-+	}
-+
-+#ifdef AuDbgHnotify
-+	au_debug(1);
-+	if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
-+		AuDbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s,"
-+		      " hi%lu\n",
-+		      watch->inode->i_ino, wd, mask, in_name(mask), cookie,
-+		      h_child_name ? h_child_name : "",
-+		      h_child_inode ? h_child_inode->i_ino : 0);
-+		WARN_ON(1);
-+	}
-+	au_debug(0);
-+#endif
-+
-+	if (h_child_name)
-+		h_child_qstr.len = strlen(h_child_name);
-+	hnotify = container_of(watch, struct au_hnotify, hn_watch);
-+	mask = au_hin_conv_mask(mask);
-+	au_hnotify(watch->inode, hnotify, mask, &h_child_qstr, h_child_inode);
-+}
-+
-+static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
-+{
-+	return;
-+}
-+
-+static struct inotify_operations aufs_inotify_ops = {
-+	.handle_event	= aufs_inotify,
-+	.destroy_watch	= aufs_inotify_destroy
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int __init au_hin_init(void)
-+{
-+	int err;
-+
-+	err = 0;
-+	au_hin_handle = inotify_init(&aufs_inotify_ops);
-+	if (IS_ERR(au_hin_handle))
-+		err = PTR_ERR(au_hin_handle);
-+
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+static void au_hin_fin(void)
-+{
-+	inotify_destroy(au_hin_handle);
-+}
-+
-+const struct au_hnotify_op au_hnotify_op = {
-+	.ctl		= au_hin_ctl,
-+	.alloc		= au_hin_alloc,
-+	.free		= au_hin_free,
-+
-+	.fin		= au_hin_fin,
-+	.init		= au_hin_init
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/hnotify.c linux-2.6.33.1/fs/aufs/hnotify.c
---- linux-2.6.33.1-vanilla/fs/aufs/hnotify.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/hnotify.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,671 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * abstraction to notify the direct changes on lower directories
-+ */
-+
-+#include "aufs.h"
-+
-+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
-+		struct inode *h_inode)
-+{
-+	int err;
-+	struct au_hnotify *hn;
-+
-+	err = -ENOMEM;
-+	hn = au_cache_alloc_hnotify();
-+	if (hn) {
-+		hn->hn_aufs_inode = inode;
-+		err = au_hnotify_op.alloc(hn, h_inode);
-+		if (!err)
-+			hinode->hi_notify = hn;
-+		else {
-+			au_cache_free_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;
-+		}
-+	}
-+
-+	return err;
-+}
-+
-+void au_hn_free(struct au_hinode *hinode)
-+{
-+	struct au_hnotify *hn;
-+
-+	hn = hinode->hi_notify;
-+	if (hn) {
-+		au_hnotify_op.free(hn);
-+		au_cache_free_hnotify(hn);
-+		hinode->hi_notify = NULL;
-+	}
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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, bend;
-+	struct inode *hi;
-+	struct dentry *iwhdentry;
-+
-+	bend = au_ibend(inode);
-+	for (bindex = au_ibstart(inode); bindex <= bend; 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, bend, bfound, bstart;
-+	struct inode *h_i;
-+
-+	err = 0;
-+	if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
-+		pr_warning("branch root dir was changed\n");
-+		goto out;
-+	}
-+
-+	bfound = -1;
-+	bend = au_ibend(inode);
-+	bstart = au_ibstart(inode);
-+#if 0 /* reserved for future use */
-+	if (bindex == bend) {
-+		/* keep this ino in rename case */
-+		goto out;
-+	}
-+#endif
-+	for (bindex = bstart; bindex <= bend; bindex++)
-+		if (au_h_iptr(inode, bindex) == h_inode) {
-+			bfound = bindex;
-+			break;
-+		}
-+	if (bfound < 0)
-+		goto out;
-+
-+	for (bindex = bstart; bindex <= bend; 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;
-+
-+			d_drop(d);
-+			au_digen_dec(d);
-+			if (d->d_inode)
-+				/* todo: reset children xino?
-+				   cached children only? */
-+				au_iigen_dec(d->d_inode);
-+		}
-+	}
-+
-+ out_dpages:
-+	au_dpages_free(&dpages);
-+
-+	/* discard children */
-+	dentry_unhash(dentry);
-+	dput(dentry);
-+ 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_warning("branch root dir was changed\n");
-+		err = 0;
-+		goto out;
-+	}
-+
-+	if (!isdir) {
-+		AuDebugOn(!name);
-+		au_iigen_dec(inode);
-+		spin_lock(&dcache_lock);
-+		list_for_each_entry(d, &inode->i_dentry, d_alias) {
-+			dname = &d->d_name;
-+			if (dname->len != nlen
-+			    && memcmp(dname->name, name, nlen))
-+				continue;
-+			err = 0;
-+			spin_lock(&d->d_lock);
-+			__d_drop(d);
-+			au_digen_dec(d);
-+			spin_unlock(&d->d_lock);
-+			break;
-+		}
-+		spin_unlock(&dcache_lock);
-+	} else {
-+		au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
-+		d = d_find_alias(inode);
-+		if (!d) {
-+			au_iigen_dec(inode);
-+			goto out;
-+		}
-+
-+		dname = &d->d_name;
-+		if (dname->len == nlen && !memcmp(dname->name, name, nlen))
-+			err = hn_gen_tree(d);
-+		dput(d);
-+	}
-+
-+ out:
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
-+{
-+	int err;
-+	struct inode *inode;
-+
-+	inode = dentry->d_inode;
-+	if (IS_ROOT(dentry)
-+	    /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
-+		) {
-+		pr_warning("branch root dir was changed\n");
-+		return 0;
-+	}
-+
-+	err = 0;
-+	if (!isdir) {
-+		d_drop(dentry);
-+		au_digen_dec(dentry);
-+		if (inode)
-+			au_iigen_dec(inode);
-+	} else {
-+		au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
-+		if (inode)
-+			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)	{ (flags) |= AuHnJob_##name; }
-+#define au_fclr_hnjob(flags, name)	{ (flags) &= ~AuHnJob_##name; }
-+
-+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);
-+
-+	/* 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)
-+			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)) {
-+		int err = -1;
-+		if (a->inode)
-+			err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
-+					      isdir);
-+		if (err && 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_warning("mount-point %.*s is removed or renamed\n",
-+			   AuDLNPair(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_alias(dir);
-+	if (!parent)
-+		return NULL;
-+
-+	dentry = NULL;
-+	spin_lock(&dcache_lock);
-+	list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
-+		/* AuDbg("%.*s\n", AuDLNPair(d)); */
-+		dname = &d->d_name;
-+		if (dname->len != nlen || memcmp(dname->name, name, nlen))
-+			continue;
-+		if (!atomic_read(&d->d_count) || !d->d_fsdata) {
-+			spin_lock(&d->d_lock);
-+			__d_drop(d);
-+			spin_unlock(&d->d_lock);
-+			continue;
-+		}
-+
-+		dentry = dget(d);
-+		break;
-+	}
-+	spin_unlock(&dcache_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_warning("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, bend, 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);
-+	/* big aufs lock */
-+	si_noflush_write_lock(sb);
-+
-+	ii_read_lock_parent(a->dir);
-+	bfound = -1;
-+	bend = au_ibend(a->dir);
-+	for (bindex = au_ibstart(a->dir); bindex <= bend; 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)
-+		inode = dentry->d_inode;
-+	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 (dentry->d_fsdata)
-+			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:
-+	au_nwt_done(&sbinfo->si_nowait);
-+	si_write_unlock(sb);
-+
-+	iput(a->h_child_inode);
-+	iput(a->h_dir);
-+	iput(a->dir);
-+	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];
-+	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 || !h_child_inode);
-+		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() */
-+	/*
-+	 * inotify_mutex is already acquired and kmalloc/prune_icache may lock
-+	 * iprune_mutex. strange.
-+	 */
-+	/* lockdep_off(); */
-+	args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
-+	/* lockdep_on(); */
-+	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;
-+	}
-+
-+	/* lockdep_off(); */
-+	err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
-+	/* lockdep_on(); */
-+	if (unlikely(err)) {
-+		pr_err("wkq %d\n", err);
-+		iput(args->h_child_inode);
-+		iput(args->h_dir);
-+		iput(args->dir);
-+		kfree(args);
-+	}
-+
-+out:
-+	return err;
-+}
-+
-+static void au_hn_destroy_cache(void)
-+{
-+	kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
-+	au_cachep[AuCache_HNOTIFY] = NULL;
-+}
-+
-+int __init au_hnotify_init(void)
-+{
-+	int err;
-+
-+	err = -ENOMEM;
-+	au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
-+	if (au_cachep[AuCache_HNOTIFY]) {
-+		err = au_hnotify_op.init();
-+		if (unlikely(err))
-+			au_hn_destroy_cache();
-+	}
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+void au_hnotify_fin(void)
-+{
-+	au_hnotify_op.fin();
-+	/* cf. au_cache_fin() */
-+	if (au_cachep[AuCache_HNOTIFY])
-+		au_hn_destroy_cache();
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/iinfo.c linux-2.6.33.1/fs/aufs/iinfo.c
---- linux-2.6.33.1-vanilla/fs/aufs/iinfo.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/iinfo.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,282 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * inode private data
-+ */
-+
-+#include "aufs.h"
-+
-+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
-+{
-+	struct inode *h_inode;
-+
-+	IiMustAnyLock(inode);
-+
-+	h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
-+	AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
-+	return h_inode;
-+}
-+
-+/* todo: hard/soft set? */
-+void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
-+{
-+	struct au_iinfo *iinfo = au_ii(inode);
-+	struct inode *h_inode;
-+
-+	IiMustWriteLock(inode);
-+
-+	iinfo->ii_bstart = bindex;
-+	h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
-+	if (h_inode)
-+		au_cpup_igen(inode, h_inode);
-+}
-+
-+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 = iinfo->ii_hinode + 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;
-+
-+		if (bindex == iinfo->ii_bstart)
-+			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, h_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_ii(inode)->ii_hinode + bindex;
-+	AuDebugOn(hinode->hi_whdentry);
-+	hinode->hi_whdentry = h_wh;
-+}
-+
-+void au_update_iigen(struct inode *inode)
-+{
-+	atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
-+	/* smp_mb(); */ /* atomic_set */
-+}
-+
-+/* it may be called at remount time, too */
-+void au_update_brange(struct inode *inode, int do_put_zero)
-+{
-+	struct au_iinfo *iinfo;
-+
-+	iinfo = au_ii(inode);
-+	if (!iinfo || iinfo->ii_bstart < 0)
-+		return;
-+
-+	IiMustWriteLock(inode);
-+
-+	if (do_put_zero) {
-+		aufs_bindex_t bindex;
-+
-+		for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
-+		     bindex++) {
-+			struct inode *h_i;
-+
-+			h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
-+			if (h_i && !h_i->i_nlink)
-+				au_set_h_iptr(inode, bindex, NULL, 0);
-+		}
-+	}
-+
-+	iinfo->ii_bstart = -1;
-+	while (++iinfo->ii_bstart <= iinfo->ii_bend)
-+		if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
-+			break;
-+	if (iinfo->ii_bstart > iinfo->ii_bend) {
-+		iinfo->ii_bstart = -1;
-+		iinfo->ii_bend = -1;
-+		return;
-+	}
-+
-+	iinfo->ii_bend++;
-+	while (0 <= --iinfo->ii_bend)
-+		if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
-+			break;
-+	AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int au_iinfo_init(struct inode *inode)
-+{
-+	struct au_iinfo *iinfo;
-+	struct super_block *sb;
-+	int nbr, i;
-+
-+	sb = inode->i_sb;
-+	iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
-+	nbr = au_sbend(sb) + 1;
-+	if (unlikely(nbr <= 0))
-+		nbr = 1;
-+	iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
-+	if (iinfo->ii_hinode) {
-+		for (i = 0; i < nbr; i++)
-+			iinfo->ii_hinode[i].hi_id = -1;
-+
-+		atomic_set(&iinfo->ii_generation, au_sigen(sb));
-+		/* smp_mb(); */ /* atomic_set */
-+		au_rw_init(&iinfo->ii_rwsem);
-+		iinfo->ii_bstart = -1;
-+		iinfo->ii_bend = -1;
-+		iinfo->ii_vdir = NULL;
-+		return 0;
-+	}
-+	return -ENOMEM;
-+}
-+
-+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
-+{
-+	int err, sz;
-+	struct au_hinode *hip;
-+
-+	AuRwMustWriteLock(&iinfo->ii_rwsem);
-+
-+	err = -ENOMEM;
-+	sz = sizeof(*hip) * (iinfo->ii_bend + 1);
-+	if (!sz)
-+		sz = sizeof(*hip);
-+	hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
-+	if (hip) {
-+		iinfo->ii_hinode = hip;
-+		err = 0;
-+	}
-+
-+	return err;
-+}
-+
-+static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
-+			   ino_t ino)
-+{
-+	int err;
-+	aufs_bindex_t bindex;
-+	unsigned char locked;
-+
-+	err = 0;
-+	locked = !!si_noflush_read_trylock(sb);
-+	bindex = au_br_index(sb, hinode->hi_id);
-+	if (bindex >= 0)
-+		err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
-+	/* error action? */
-+	if (locked)
-+		si_read_unlock(sb);
-+	return err;
-+}
-+
-+void au_iinfo_fin(struct inode *inode)
-+{
-+	ino_t ino;
-+	aufs_bindex_t bend;
-+	unsigned char unlinked = !inode->i_nlink;
-+	struct au_iinfo *iinfo;
-+	struct au_hinode *hi;
-+	struct super_block *sb;
-+
-+	if (unlinked) {
-+		int err = au_xigen_inc(inode);
-+		if (unlikely(err))
-+			AuWarn1("failed resetting i_generation, %d\n", err);
-+	}
-+
-+	iinfo = au_ii(inode);
-+	/* bad_inode case */
-+	if (!iinfo)
-+		return;
-+
-+	if (iinfo->ii_vdir)
-+		au_vdir_free(iinfo->ii_vdir);
-+
-+	if (iinfo->ii_bstart >= 0) {
-+		sb = inode->i_sb;
-+		ino = 0;
-+		if (unlinked)
-+			ino = inode->i_ino;
-+		hi = iinfo->ii_hinode + iinfo->ii_bstart;
-+		bend = iinfo->ii_bend;
-+		while (iinfo->ii_bstart++ <= bend) {
-+			if (hi->hi_inode) {
-+				if (unlinked || !hi->hi_inode->i_nlink) {
-+					au_iinfo_write0(sb, hi, ino);
-+					/* ignore this error */
-+					ino = 0;
-+				}
-+				au_hiput(hi);
-+			}
-+			hi++;
-+		}
-+	}
-+
-+	kfree(iinfo->ii_hinode);
-+	AuRwDestroy(&iinfo->ii_rwsem);
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/inode.c linux-2.6.33.1/fs/aufs/inode.c
---- linux-2.6.33.1-vanilla/fs/aufs/inode.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/inode.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,412 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * inode functions
-+ */
-+
-+#include "aufs.h"
-+
-+struct inode *au_igrab(struct inode *inode)
-+{
-+	if (inode) {
-+		AuDebugOn(!atomic_read(&inode->i_count));
-+		atomic_inc_return(&inode->i_count);
-+	}
-+	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);
-+	if (do_version)
-+		inode->i_version++;
-+}
-+
-+int au_refresh_hinode_self(struct inode *inode, int do_attr)
-+{
-+	int err;
-+	aufs_bindex_t bindex, new_bindex;
-+	unsigned char update;
-+	struct au_hinode *p, *q, tmp;
-+	struct super_block *sb;
-+	struct au_iinfo *iinfo;
-+
-+	IiMustWriteLock(inode);
-+
-+	update = 0;
-+	sb = inode->i_sb;
-+	iinfo = au_ii(inode);
-+	err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
-+	if (unlikely(err))
-+		goto out;
-+
-+	p = iinfo->ii_hinode + iinfo->ii_bstart;
-+	err = 0;
-+	for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
-+	     bindex++, p++) {
-+		if (!p->hi_inode)
-+			continue;
-+
-+		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_bstart)
-+			iinfo->ii_bstart = new_bindex;
-+		if (iinfo->ii_bend < new_bindex)
-+			iinfo->ii_bend = new_bindex;
-+		/* swap two lower inode, and loop again */
-+		q = iinfo->ii_hinode + new_bindex;
-+		tmp = *q;
-+		*q = *p;
-+		*p = tmp;
-+		if (tmp.hi_inode) {
-+			bindex--;
-+			p--;
-+		}
-+	}
-+	au_update_brange(inode, /*do_put_zero*/0);
-+	if (do_attr)
-+		au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
-+
-+ out:
-+	return err;
-+}
-+
-+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
-+{
-+	int err;
-+	unsigned int flags;
-+	aufs_bindex_t bindex, bend;
-+	unsigned char isdir, update;
-+	struct au_hinode *p;
-+	struct au_iinfo *iinfo;
-+
-+	err = au_refresh_hinode_self(inode, /*do_attr*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	update = 0;
-+	iinfo = au_ii(inode);
-+	p = iinfo->ii_hinode + iinfo->ii_bstart;
-+	isdir = S_ISDIR(inode->i_mode);
-+	flags = au_hi_flags(inode, isdir);
-+	bend = au_dbend(dentry);
-+	for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
-+		struct inode *h_i;
-+		struct dentry *h_d;
-+
-+		h_d = au_h_dptr(dentry, bindex);
-+		if (!h_d || !h_d->d_inode)
-+			continue;
-+
-+		if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
-+			h_i = au_h_iptr(inode, bindex);
-+			if (h_i) {
-+				if (h_i == h_d->d_inode)
-+					continue;
-+				err = -EIO;
-+				break;
-+			}
-+		}
-+		if (bindex < iinfo->ii_bstart)
-+			iinfo->ii_bstart = bindex;
-+		if (iinfo->ii_bend < bindex)
-+			iinfo->ii_bend = bindex;
-+		au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
-+		update = 1;
-+	}
-+	au_update_brange(inode, /*do_put_zero*/0);
-+
-+	if (unlikely(err))
-+		goto out;
-+
-+	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, bstart, btail;
-+	unsigned char isdir;
-+	struct dentry *h_dentry;
-+	struct inode *h_inode;
-+	struct au_iinfo *iinfo;
-+
-+	IiMustWriteLock(inode);
-+
-+	err = 0;
-+	isdir = 0;
-+	bstart = au_dbstart(dentry);
-+	h_inode = au_h_dptr(dentry, bstart)->d_inode;
-+	mode = h_inode->i_mode;
-+	switch (mode & S_IFMT) {
-+	case S_IFREG:
-+		btail = au_dbtail(dentry);
-+		inode->i_op = &aufs_iop;
-+		inode->i_fop = &aufs_file_fop;
-+		inode->i_mapping->a_ops = &aufs_aop;
-+		break;
-+	case S_IFDIR:
-+		isdir = 1;
-+		btail = au_dbtaildir(dentry);
-+		inode->i_op = &aufs_dir_iop;
-+		inode->i_fop = &aufs_dir_fop;
-+		break;
-+	case S_IFLNK:
-+		btail = au_dbtail(dentry);
-+		inode->i_op = &aufs_symlink_iop;
-+		break;
-+	case S_IFBLK:
-+	case S_IFCHR:
-+	case S_IFIFO:
-+	case S_IFSOCK:
-+		btail = au_dbtail(dentry);
-+		inode->i_op = &aufs_iop;
-+		au_init_special_fop(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_bstart = bstart;
-+	iinfo->ii_bend = btail;
-+	for (bindex = bstart; bindex <= btail; bindex++) {
-+		h_dentry = au_h_dptr(dentry, bindex);
-+		if (h_dentry)
-+			au_set_h_iptr(inode, bindex,
-+				      au_igrab(h_dentry->d_inode), flags);
-+	}
-+	au_cpup_attr_all(inode, /*force*/1);
-+
-+ out:
-+	return err;
-+}
-+
-+/* successful returns with iinfo write_locked */
-+static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
-+{
-+	int err;
-+	aufs_bindex_t bindex, bend;
-+	struct inode *h_inode, *h_dinode;
-+
-+	*matched = 0;
-+
-+	/*
-+	 * 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 = 0;
-+	ii_write_lock_new_child(inode);
-+	h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
-+	bend = au_ibend(inode);
-+	for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
-+		h_inode = au_h_iptr(inode, bindex);
-+		if (h_inode && h_inode == h_dinode) {
-+			*matched = 1;
-+			err = 0;
-+			if (au_iigen(inode) != au_digen(dentry))
-+				err = au_refresh_hinode(inode, dentry);
-+			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;
-+	const int isdir = (d_type == DT_DIR);
-+
-+	/* prevent hardlinks from race condition */
-+	mtx = NULL;
-+	if (!isdir) {
-+		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 (!isdir)
-+		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;
-+	struct dentry *h_dentry;
-+	struct super_block *sb;
-+	ino_t h_ino, ino;
-+	int err, match;
-+	aufs_bindex_t bstart;
-+
-+	sb = dentry->d_sb;
-+	bstart = au_dbstart(dentry);
-+	h_dentry = au_h_dptr(dentry, bstart);
-+	h_ino = h_dentry->d_inode->i_ino;
-+	err = au_xino_read(sb, bstart, h_ino, &ino);
-+	inode = ERR_PTR(err);
-+	if (unlikely(err))
-+		goto out;
-+ new_ino:
-+	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 */
-+		}
-+
-+		ii_write_unlock(inode);
-+		iget_failed(inode);
-+		goto out_err;
-+	} else if (!must_new) {
-+		err = reval_inode(inode, dentry, &match);
-+		if (!err)
-+			goto out; /* success */
-+		else if (match)
-+			goto out_iput;
-+	}
-+
-+	if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
-+		AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
-+			" b%d, %s, %.*s, hi%lu, i%lu.\n",
-+			bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
-+			(unsigned long)h_ino, (unsigned long)ino);
-+	ino = 0;
-+	err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
-+	if (!err) {
-+		iput(inode);
-+		goto new_ino;
-+	}
-+
-+ out_iput:
-+	iput(inode);
-+ out_err:
-+	inode = ERR_PTR(err);
-+ out:
-+	return inode;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
-+	       struct inode *inode)
-+{
-+	int err;
-+
-+	err = au_br_rdonly(au_sbr(sb, bindex));
-+
-+	/* pseudo-link after flushed may happen out of bounds */
-+	if (!err
-+	    && inode
-+	    && au_ibstart(inode) <= bindex
-+	    && bindex <= au_ibend(inode)) {
-+		/*
-+		 * permission check is unnecessary since vfsub routine
-+		 * will be called later
-+		 */
-+		struct inode *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 (!current_fsuid())
-+		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 -Nur linux-2.6.33.1-vanilla/fs/aufs/inode.h linux-2.6.33.1/fs/aufs/inode.h
---- linux-2.6.33.1-vanilla/fs/aufs/inode.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/inode.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,492 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * inode operations
-+ */
-+
-+#ifndef __AUFS_INODE_H__
-+#define __AUFS_INODE_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/fsnotify.h>
-+#include <linux/aufs_type.h>
-+#include "rwsem.h"
-+
-+struct vfsmount;
-+
-+struct au_hnotify {
-+#ifdef CONFIG_AUFS_HNOTIFY
-+#ifdef CONFIG_AUFS_HFSNOTIFY
-+	struct fsnotify_mark_entry	hn_entry;
-+#else
-+	struct inotify_watch		hn_watch;
-+#endif
-+	struct inode			*hn_aufs_inode;	/* no get/put */
-+#endif
-+};
-+
-+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;
-+};
-+
-+struct au_vdir;
-+struct au_iinfo {
-+	atomic_t		ii_generation;
-+	struct super_block	*ii_hsb1;	/* no get/put */
-+
-+	struct au_rwsem		ii_rwsem;
-+	aufs_bindex_t		ii_bstart, ii_bend;
-+	__u32			ii_higen;
-+	struct au_hinode	*ii_hinode;
-+	struct au_vdir		*ii_vdir;
-+};
-+
-+struct au_icntnr {
-+	struct au_iinfo iinfo;
-+	struct inode vfs_inode;
-+};
-+
-+/* 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)	{ (flags) |= AuPin_##name; }
-+#define au_fclr_pin(flags, name)	{ (flags) &= ~AuPin_##name; }
-+
-+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;
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline struct au_iinfo *au_ii(struct inode *inode)
-+{
-+	struct au_iinfo *iinfo;
-+
-+	iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
-+	if (iinfo->ii_hinode)
-+		return iinfo;
-+	return NULL; /* debugging bad_inode case */
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* inode.c */
-+struct inode *au_igrab(struct inode *inode);
-+int au_refresh_hinode_self(struct inode *inode, int do_attr);
-+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 */
-+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
-+
-+/* au_wr_dir flags */
-+#define AuWrDir_ADD_ENTRY	1
-+#define AuWrDir_ISDIR		(1 << 1)
-+#define au_ftest_wrdir(flags, name)	((flags) & AuWrDir_##name)
-+#define au_fset_wrdir(flags, name)	{ (flags) |= AuWrDir_##name; }
-+#define au_fclr_wrdir(flags, name)	{ (flags) &= ~AuWrDir_##name; }
-+
-+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);
-+
-+/* 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, int 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, int mode,
-+		struct nameidata *nd);
-+int aufs_link(struct dentry *src_dentry, struct inode *dir,
-+	      struct dentry *dentry);
-+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int 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_ibstart(struct inode *inode, aufs_bindex_t bindex);
-+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)		{ (flags) |= AuHi_##name; }
-+#define au_fclr_hi(flags, name)		{ (flags) &= ~AuHi_##name; }
-+
-+#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);
-+void au_update_brange(struct inode *inode, int do_put_zero);
-+
-+int au_iinfo_init(struct inode *inode);
-+void au_iinfo_fin(struct inode *inode);
-+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
-+
-+/* plink.c */
-+void au_plink_maint_block(struct super_block *sb);
-+void au_plink_maint_leave(struct file *file);
-+#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);
-+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
-+long au_plink_ioctl(struct file *file, unsigned int cmd);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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 unsigned int au_iigen(struct inode *inode)
-+{
-+	return atomic_read(&au_ii(inode)->ii_generation);
-+}
-+
-+/* 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)
-+{
-+#ifdef CONFIG_AUFS_HNOTIFY
-+	atomic_dec_return(&au_ii(inode)->ii_generation);
-+#endif
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
-+					aufs_bindex_t bindex)
-+{
-+	IiMustAnyLock(inode);
-+	return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
-+}
-+
-+static inline aufs_bindex_t au_ibstart(struct inode *inode)
-+{
-+	IiMustAnyLock(inode);
-+	return au_ii(inode)->ii_bstart;
-+}
-+
-+static inline aufs_bindex_t au_ibend(struct inode *inode)
-+{
-+	IiMustAnyLock(inode);
-+	return au_ii(inode)->ii_bend;
-+}
-+
-+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_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
-+}
-+
-+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
-+{
-+	IiMustWriteLock(inode);
-+	au_ii(inode)->ii_bend = 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_ii(inode)->ii_hinode + 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) {
-+		/* dirty macros require brackets */
-+		if (lflag) {
-+			au_fset_pin(pin->flags, DI_LOCKED);
-+		} else {
-+			au_fclr_pin(pin->flags, DI_LOCKED);
-+		}
-+	}
-+}
-+
-+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
-+{
-+	if (pin) {
-+		dput(pin->parent);
-+		pin->parent = dget(parent);
-+	}
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+#ifdef CONFIG_AUFS_HNOTIFY
-+struct au_hnotify_op {
-+	void (*ctl)(struct au_hinode *hinode, int do_set);
-+	int (*alloc)(struct au_hnotify *hn, struct inode *h_inode);
-+	void (*free)(struct au_hnotify *hn);
-+
-+	void (*fin)(void);
-+	int (*init)(void);
-+};
-+
-+/* hnotify.c */
-+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode,
-+		struct inode *h_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 __init au_hnotify_init(void);
-+void au_hnotify_fin(void);
-+
-+/* hinotify.c */
-+extern const struct au_hnotify_op au_hnotify_op;
-+
-+static inline
-+void au_hn_init(struct au_hinode *hinode)
-+{
-+	hinode->hi_notify = NULL;
-+}
-+
-+#else
-+static inline
-+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
-+		struct inode *inode __maybe_unused,
-+		struct inode *h_inode __maybe_unused)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+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(__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 -Nur linux-2.6.33.1-vanilla/fs/aufs/ioctl.c linux-2.6.33.1/fs/aufs/ioctl.c
---- linux-2.6.33.1-vanilla/fs/aufs/ioctl.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/ioctl.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,129 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * ioctl
-+ * plink-management and readdir in userspace.
-+ * assist the pathconf(3) wrapper library.
-+ */
-+
-+#include <linux/file.h>
-+#include "aufs.h"
-+
-+static int au_wbr_fd(struct path *path)
-+{
-+	int err, fd, flags;
-+	aufs_bindex_t wbi, bindex, bend;
-+	struct file *h_file;
-+	struct super_block *sb;
-+	struct dentry *root;
-+	struct au_branch *wbr;
-+
-+	err = get_unused_fd();
-+	if (unlikely(err < 0))
-+		goto out;
-+	fd = err;
-+
-+	flags = O_RDONLY | O_DIRECTORY;
-+	if (force_o_largefile())
-+		flags |= O_LARGEFILE;
-+
-+	wbi = 0;
-+	sb = path->dentry->d_sb;
-+	root = sb->s_root;
-+	aufs_read_lock(root, AuLock_IR);
-+	wbr = au_sbr(sb, wbi);
-+	if (!(path->mnt->mnt_flags & MNT_READONLY)
-+	    && !au_br_writable(wbr->br_perm)) {
-+		bend = au_sbend(sb);
-+		for (bindex = 1; bindex <= bend; bindex++) {
-+			wbr = au_sbr(sb, bindex);
-+			if (au_br_writable(wbr->br_perm)) {
-+				wbi = bindex;
-+				break;
-+			}
-+		}
-+		wbr = au_sbr(sb, wbi);
-+	}
-+	AuDbg("wbi %d\n", wbi);
-+	h_file = au_h_open(root, wbi, flags, NULL);
-+	aufs_read_unlock(root, AuLock_IR);
-+	err = PTR_ERR(h_file);
-+	if (IS_ERR(h_file))
-+		goto out_fd;
-+
-+	atomic_dec(&wbr->br_count); /* cf. au_h_open() */
-+	fd_install(fd, h_file);
-+	err = fd;
-+	goto out; /* success */
-+
-+ out_fd:
-+	put_unused_fd(fd);
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+	long err;
-+
-+	switch (cmd) {
-+	case AUFS_CTL_PLINK_MAINT:
-+	case AUFS_CTL_PLINK_CLEAN:
-+		err = au_plink_ioctl(file, cmd);
-+		break;
-+
-+	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);
-+		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_WBR_FD:
-+		err = au_wbr_fd(&file->f_path);
-+		break;
-+
-+	default:
-+		/* do not call the lower */
-+		AuDbg("0x%x\n", cmd);
-+		err = -ENOTTY;
-+	}
-+
-+	AuTraceErr(err);
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_add.c \
                linux-2.6.33.1/fs/aufs/i_op_add.c
---- linux-2.6.33.1-vanilla/fs/aufs/i_op_add.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/i_op_add.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,672 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 inode *inode, *h_dir;
-+	struct dentry *wh;
-+
-+	bwh = -1;
-+	if (wh_dentry) {
-+		h_dir = wh_dentry->d_parent->d_inode; /* 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(dir->i_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 = dentry->d_parent->d_inode; /* dir inode is locked */
-+		IMustLock(dir);
-+		if (au_ibstart(dir) == au_dbstart(dentry))
-+			au_cpup_attr_timesizes(dir);
-+		dir->i_version++;
-+		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("%.*s reverting whiteout failed(%d, %d)\n",
-+			AuDLNPair(dentry), err, rerr);
-+		err = -EIO;
-+	} else
-+		dput(wh);
-+
-+ out:
-+	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);
-+	h_inode = h_dentry->d_inode;
-+	if (!dentry->d_inode) {
-+		err = -EEXIST;
-+		if (unlikely(h_inode))
-+			goto out;
-+	} else {
-+		/* rename(2) case */
-+		err = -EIO;
-+		if (unlikely(!h_inode || !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("%.*s\n", AuDLNPair(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_dbstart(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	= br->br_mnt
-+		};
-+		au_dtime_store(dt, au_pinned_parent(pin), &tmp);
-+	}
-+
-+	wh_dentry = NULL;
-+	if (bcpup != au_dbwh(dentry))
-+		goto out; /* success */
-+
-+	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 {
-+			int mode;
-+			struct nameidata *nd;
-+		} c;
-+		struct {
-+			const char *symname;
-+		} s;
-+		struct {
-+			int mode;
-+			dev_t dev;
-+		} m;
-+	} u;
-+};
-+
-+static int add_simple(struct inode *dir, struct dentry *dentry,
-+		      struct simple_arg *arg)
-+{
-+	int err;
-+	aufs_bindex_t bstart;
-+	unsigned char created;
-+	struct au_dtime dt;
-+	struct au_pin pin;
-+	struct path h_path;
-+	struct dentry *wh_dentry, *parent;
-+	struct inode *h_dir;
-+	struct au_wr_dir_args wr_dir_args = {
-+		.force_btgt	= -1,
-+		.flags		= AuWrDir_ADD_ENTRY
-+	};
-+
-+	AuDbg("%.*s\n", AuDLNPair(dentry));
-+	IMustLock(dir);
-+
-+	parent = dentry->d_parent; /* dir inode is locked */
-+	aufs_read_lock(dentry, AuLock_DW);
-+	di_write_lock_parent(parent);
-+	wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
-+				      &wr_dir_args);
-+	err = PTR_ERR(wh_dentry);
-+	if (IS_ERR(wh_dentry))
-+		goto out;
-+
-+	bstart = au_dbstart(dentry);
-+	h_path.dentry = au_h_dptr(dentry, bstart);
-+	h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
-+	h_dir = au_pinned_h_dir(&pin);
-+	switch (arg->type) {
-+	case Creat:
-+		err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
-+		break;
-+	case Symlink:
-+		err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
-+		break;
-+	case Mknod:
-+		err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
-+		break;
-+	default:
-+		BUG();
-+	}
-+	created = !err;
-+	if (!err)
-+		err = epilog(dir, bstart, wh_dentry, dentry);
-+
-+	/* revert */
-+	if (unlikely(created && err && h_path.dentry->d_inode)) {
-+		int rerr;
-+		rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
-+		if (rerr) {
-+			AuIOErr("%.*s revert failure(%d, %d)\n",
-+				AuDLNPair(dentry), err, rerr);
-+			err = -EIO;
-+		}
-+		au_dtime_revert(&dt);
-+		d_drop(dentry);
-+	}
-+
-+	au_unpin(&pin);
-+	dput(wh_dentry);
-+
-+ out:
-+	if (unlikely(err)) {
-+		au_update_dbstart(dentry);
-+		d_drop(dentry);
-+	}
-+	di_write_unlock(parent);
-+	aufs_read_unlock(dentry, AuLock_DW);
-+	return err;
-+}
-+
-+int aufs_mknod(struct inode *dir, struct dentry *dentry, int 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, int mode,
-+		struct nameidata *nd)
-+{
-+	struct simple_arg arg = {
-+		.type = Creat,
-+		.u.c = {
-+			.mode	= mode,
-+			.nd	= nd
-+		}
-+	};
-+	return add_simple(dir, dentry, &arg);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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 mutex *h_mtx;
-+	struct file *h_file;
-+
-+	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);
-+	h_mtx = &h_src_dentry->d_inode->i_mutex;
-+	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;
-+	mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+	h_file = au_h_open_pre(src_dentry, a->bsrc);
-+	if (IS_ERR(h_file)) {
-+		err = PTR_ERR(h_file);
-+		h_file = NULL;
-+	} else
-+		err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
-+					 AuCpup_DTIME /* | AuCpup_KEEPLINO */);
-+	mutex_unlock(h_mtx);
-+	au_h_open_post(src_dentry, a->bsrc, h_file);
-+	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 au_link_args *a)
-+{
-+	int err;
-+	unsigned char plink;
-+	struct inode *h_inode, *inode;
-+	struct dentry *h_src_dentry;
-+	struct super_block *sb;
-+	struct file *h_file;
-+
-+	plink = 0;
-+	h_inode = NULL;
-+	sb = src_dentry->d_sb;
-+	inode = src_dentry->d_inode;
-+	if (au_ibstart(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. */
-+		au_set_dbstart(src_dentry, a->bdst);
-+		au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
-+		h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
-+		mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+		h_file = au_h_open_pre(src_dentry, a->bsrc);
-+		if (IS_ERR(h_file)) {
-+			err = PTR_ERR(h_file);
-+			h_file = NULL;
-+		} else
-+			err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
-+						 -1, AuCpup_KEEPLINO,
-+						 a->parent);
-+		mutex_unlock(&h_inode->i_mutex);
-+		au_h_open_post(src_dentry, a->bsrc, h_file);
-+		au_set_h_dptr(src_dentry, a->bdst, NULL);
-+		au_set_dbstart(src_dentry, a->bsrc);
-+	} 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(!h_src_dentry->d_inode)) {
-+				dput(h_src_dentry);
-+				h_src_dentry = NULL;
-+			}
-+
-+		}
-+		if (h_src_dentry) {
-+			err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
-+					 &a->h_path);
-+			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:
-+	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;
-+	struct super_block *sb;
-+	struct au_wr_dir_args wr_dir_args = {
-+		/* .force_btgt	= -1, */
-+		.flags		= AuWrDir_ADD_ENTRY
-+	};
-+
-+	IMustLock(dir);
-+	inode = src_dentry->d_inode;
-+	IMustLock(inode);
-+
-+	err = -ENOENT;
-+	if (unlikely(!inode->i_nlink))
-+		goto out;
-+
-+	err = -ENOMEM;
-+	a = kzalloc(sizeof(*a), GFP_NOFS);
-+	if (unlikely(!a))
-+		goto out;
-+
-+	a->parent = dentry->d_parent; /* dir inode is locked */
-+	aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
-+	a->src_parent = dget_parent(src_dentry);
-+	wr_dir_args.force_btgt = au_dbstart(src_dentry);
-+
-+	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_unlock;
-+
-+	err = 0;
-+	sb = dentry->d_sb;
-+	a->bdst = au_dbstart(dentry);
-+	a->h_path.dentry = au_h_dptr(dentry, a->bdst);
-+	a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
-+	a->bsrc = au_dbstart(src_dentry);
-+	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, a);
-+		else {
-+			h_src_dentry = au_h_dptr(src_dentry, a->bdst);
-+			err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
-+					 &a->h_path);
-+		}
-+	} else {
-+		/*
-+		 * copyup src_dentry to the branch we process,
-+		 * and then link(2) to it.
-+		 */
-+		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 && h_src_dentry->d_inode)
-+				err = vfsub_link(h_src_dentry,
-+						 au_pinned_h_dir(&a->pin),
-+						 &a->h_path);
-+		}
-+	}
-+	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;
-+	}
-+
-+	dir->i_version++;
-+	if (au_ibstart(dir) == au_dbstart(dentry))
-+		au_cpup_attr_timesizes(dir);
-+	inc_nlink(inode);
-+	inode->i_ctime = dir->i_ctime;
-+	if (!d_unhashed(a->h_path.dentry))
-+		d_instantiate(dentry, au_igrab(inode));
-+	else
-+		/* some filesystem calls d_drop() */
-+		d_drop(dentry);
-+	goto out_unpin; /* success */
-+
-+ out_revert:
-+	rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
-+	if (!rerr)
-+		goto out_dt;
-+	AuIOErr("%.*s reverting failed(%d, %d)\n",
-+		AuDLNPair(dentry), err, rerr);
-+	err = -EIO;
-+ out_dt:
-+	d_drop(dentry);
-+	au_dtime_revert(&dt);
-+ out_unpin:
-+	au_unpin(&a->pin);
-+ out_wh:
-+	dput(wh_dentry);
-+ out_unlock:
-+	if (unlikely(err)) {
-+		au_update_dbstart(dentry);
-+		d_drop(dentry);
-+	}
-+	di_write_unlock(a->parent);
-+	dput(a->src_parent);
-+	aufs_read_and_write_unlock2(dentry, src_dentry);
-+	kfree(a);
-+ out:
-+	return err;
-+}
-+
-+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int 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;
-+
-+	aufs_read_lock(dentry, AuLock_DW);
-+	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_free;
-+
-+	sb = dentry->d_sb;
-+	bindex = au_dbstart(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_unlock;
-+
-+	/* make the dir opaque */
-+	diropq = 0;
-+	h_mtx = &h_path.dentry->d_inode->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_unlock; /* 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("%.*s reverting diropq failed(%d, %d)\n",
-+				AuDLNPair(dentry), err, rerr);
-+			err = -EIO;
-+		}
-+	}
-+
-+ out_dir:
-+	AuLabel(revert dir);
-+	rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
-+	if (rerr) {
-+		AuIOErr("%.*s reverting dir failed(%d, %d)\n",
-+			AuDLNPair(dentry), err, rerr);
-+		err = -EIO;
-+	}
-+	d_drop(dentry);
-+	au_dtime_revert(&a->dt);
-+ out_unlock:
-+	au_unpin(&a->pin);
-+	dput(wh_dentry);
-+ out_free:
-+	if (unlikely(err)) {
-+		au_update_dbstart(dentry);
-+		d_drop(dentry);
-+	}
-+	di_write_unlock(parent);
-+	aufs_read_unlock(dentry, AuLock_DW);
-+	kfree(a);
-+ out:
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op.c linux-2.6.33.1/fs/aufs/i_op.c
---- linux-2.6.33.1-vanilla/fs/aufs/i_op.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/i_op.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,909 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * inode operations (except add/del/rename)
-+ */
-+
-+#include <linux/device_cgroup.h>
-+#include <linux/fs_stack.h>
-+#include <linux/mm.h>
-+#include <linux/namei.h>
-+#include <linux/security.h>
-+#include <linux/uaccess.h>
-+#include "aufs.h"
-+
-+static int h_permission(struct inode *h_inode, int mask,
-+			struct vfsmount *h_mnt, 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)
-+		&& ((h_mnt->mnt_flags & MNT_NOEXEC)
-+		    || !(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.
-+	 */
-+	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); */
-+		err = generic_permission(h_inode, mask,
-+					 h_inode->i_op->check_acl);
-+	} 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) {
-+		mask &= (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND);
-+		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, bend;
-+	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;
-+
-+	sb = inode->i_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	ii_read_lock_child(inode);
-+
-+	if (!isdir || write_mask) {
-+		err = au_busy_or_stale();
-+		h_inode = au_h_iptr(inode, au_ibstart(inode));
-+		if (unlikely(!h_inode
-+			     || (h_inode->i_mode & S_IFMT)
-+			     != (inode->i_mode & S_IFMT)))
-+			goto out;
-+
-+		err = 0;
-+		bindex = au_ibstart(inode);
-+		br = au_sbr(sb, bindex);
-+		err = h_permission(h_inode, mask, br->br_mnt, 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;
-+	bend = au_ibend(inode);
-+	for (bindex = au_ibstart(inode); !err && bindex <= bend; 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_mnt,
-+					   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,
-+				  struct nameidata *nd)
-+{
-+	struct dentry *ret, *parent;
-+	struct inode *inode, *h_inode;
-+	struct mutex *mtx;
-+	struct super_block *sb;
-+	int err, npositive;
-+	aufs_bindex_t bstart;
-+
-+	IMustLock(dir);
-+
-+	sb = dir->i_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	ret = ERR_PTR(-ENAMETOOLONG);
-+	if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
-+		goto out;
-+	err = au_alloc_dinfo(dentry);
-+	ret = ERR_PTR(err);
-+	if (unlikely(err))
-+		goto out;
-+
-+	parent = dentry->d_parent; /* dir inode is locked */
-+	di_read_lock_parent(parent, AuLock_IR);
-+	npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
-+	di_read_unlock(parent, AuLock_IR);
-+	err = npositive;
-+	ret = ERR_PTR(err);
-+	if (unlikely(err < 0))
-+		goto out_unlock;
-+
-+	inode = NULL;
-+	if (npositive) {
-+		bstart = au_dbstart(dentry);
-+		h_inode = au_h_dptr(dentry, bstart)->d_inode;
-+		if (!S_ISDIR(h_inode->i_mode)) {
-+			/*
-+			 * stop 'race'-ing between hardlinks under different
-+			 * parents.
-+			 */
-+			mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
-+			mutex_lock(mtx);
-+			inode = au_new_inode(dentry, /*must_new*/0);
-+			mutex_unlock(mtx);
-+		} else
-+			inode = au_new_inode(dentry, /*must_new*/0);
-+		ret = (void *)inode;
-+	}
-+	if (IS_ERR(inode))
-+		goto out_unlock;
-+
-+	ret = d_splice_alias(inode, dentry);
-+	if (unlikely(IS_ERR(ret) && inode))
-+		ii_write_unlock(inode);
-+
-+ out_unlock:
-+	di_write_unlock(dentry);
-+ out:
-+	si_read_unlock(sb);
-+	return ret;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
-+			  const unsigned char add_entry, aufs_bindex_t bcpup,
-+			  aufs_bindex_t bstart)
-+{
-+	int err;
-+	struct dentry *h_parent;
-+	struct inode *h_dir;
-+
-+	if (add_entry) {
-+		au_update_dbstart(dentry);
-+		IMustLock(parent->d_inode);
-+	} else
-+		di_write_lock_parent(parent);
-+
-+	err = 0;
-+	if (!au_h_dptr(parent, bcpup)) {
-+		if (bstart < bcpup)
-+			err = au_cpdown_dirs(dentry, bcpup);
-+		else
-+			err = au_cpup_dirs(dentry, bcpup);
-+	}
-+	if (!err && add_entry) {
-+		h_parent = au_h_dptr(parent, bcpup);
-+		h_dir = h_parent->d_inode;
-+		mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
-+		err = au_lkup_neg(dentry, bcpup);
-+		/* todo: no unlock here */
-+		mutex_unlock(&h_dir->i_mutex);
-+		if (bstart < bcpup && au_dbstart(dentry) < 0) {
-+			au_set_dbstart(dentry, 0);
-+			au_update_dbrange(dentry, /*do_put_zero*/0);
-+		}
-+	}
-+
-+	if (!add_entry)
-+		di_write_unlock(parent);
-+	if (!err)
-+		err = bcpup; /* success */
-+
-+	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;
-+	aufs_bindex_t bcpup, bstart, src_bstart;
-+	const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
-+							 ADD_ENTRY);
-+	struct super_block *sb;
-+	struct dentry *parent;
-+	struct au_sbinfo *sbinfo;
-+
-+	sb = dentry->d_sb;
-+	sbinfo = au_sbi(sb);
-+	parent = dget_parent(dentry);
-+	bstart = au_dbstart(dentry);
-+	bcpup = bstart;
-+	if (args->force_btgt < 0) {
-+		if (src_dentry) {
-+			src_bstart = au_dbstart(src_dentry);
-+			if (src_bstart < bstart)
-+				bcpup = src_bstart;
-+		} else if (add_entry) {
-+			err = AuWbrCreate(sbinfo, dentry,
-+					  au_ftest_wrdir(args->flags, ISDIR));
-+			bcpup = err;
-+		}
-+
-+		if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
-+			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, dentry->d_inode));
-+	}
-+	AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
-+	if (bstart < bcpup)
-+		au_update_dbrange(dentry, /*do_put_zero*/1);
-+
-+	err = bcpup;
-+	if (bcpup == bstart)
-+		goto out; /* success */
-+
-+	/* copyup the new parent into the branch we process */
-+	err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
-+
-+ out:
-+	dput(parent);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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 (au_ftest_pin(p->flags, MNT_WRITE))
-+		mnt_drop_write(p->h_mnt);
-+	if (!p->hdir)
-+		return;
-+
-+	au_hn_imtx_unlock(p->hdir);
-+	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;
-+}
-+
-+int au_do_pin(struct au_pin *p)
-+{
-+	int err;
-+	struct super_block *sb;
-+	struct dentry *h_dentry, *h_parent;
-+	struct au_branch *br;
-+	struct inode *h_dir;
-+
-+	err = 0;
-+	sb = p->dentry->d_sb;
-+	br = au_sbr(sb, p->bindex);
-+	if (IS_ROOT(p->dentry)) {
-+		if (au_ftest_pin(p->flags, MNT_WRITE)) {
-+			p->h_mnt = br->br_mnt;
-+			err = mnt_want_write(p->h_mnt);
-+			if (unlikely(err)) {
-+				au_fclr_pin(p->flags, MNT_WRITE);
-+				goto out_err;
-+			}
-+		}
-+		goto out;
-+	}
-+
-+	h_dentry = NULL;
-+	if (p->bindex <= au_dbend(p->dentry))
-+		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;
-+	h_parent = au_h_dptr(p->parent, p->bindex);
-+	p->hdir = au_hi(p->parent->d_inode, p->bindex);
-+	if (p->hdir)
-+		h_dir = p->hdir->hi_inode;
-+
-+	/* udba case */
-+	if (unlikely(!p->hdir || !h_dir)) {
-+		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);
-+	au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
-+
-+	if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
-+		err = -EBUSY;
-+		goto out_unpin;
-+	}
-+	if (h_dentry) {
-+		err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
-+		if (unlikely(err)) {
-+			au_fclr_pin(p->flags, MNT_WRITE);
-+			goto out_unpin;
-+		}
-+	}
-+
-+	if (au_ftest_pin(p->flags, MNT_WRITE)) {
-+		p->h_mnt = br->br_mnt;
-+		err = mnt_want_write(p->h_mnt);
-+		if (unlikely(err)) {
-+			au_fclr_pin(p->flags, MNT_WRITE);
-+			goto out_unpin;
-+		}
-+	}
-+	goto out; /* success */
-+
-+ out_unpin:
-+	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;
-+}
-+
-+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);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+#define AuIcpup_DID_CPUP	1
-+#define au_ftest_icpup(flags, name)	((flags) & AuIcpup_##name)
-+#define au_fset_icpup(flags, name)	{ (flags) |= AuIcpup_##name; }
-+#define au_fclr_icpup(flags, name)	{ (flags) &= ~AuIcpup_##name; }
-+
-+struct au_icpup_args {
-+	unsigned char flags;
-+	unsigned char pin_flags;
-+	aufs_bindex_t btgt;
-+	struct au_pin pin;
-+	struct path h_path;
-+	struct inode *h_inode;
-+};
-+
-+static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
-+			     struct au_icpup_args *a)
-+{
-+	int err;
-+	unsigned int udba;
-+	loff_t sz;
-+	aufs_bindex_t bstart;
-+	struct dentry *hi_wh, *parent;
-+	struct inode *inode;
-+	struct file *h_file;
-+	struct au_wr_dir_args wr_dir_args = {
-+		.force_btgt	= -1,
-+		.flags		= 0
-+	};
-+
-+	di_write_lock_child(dentry);
-+	bstart = au_dbstart(dentry);
-+	inode = dentry->d_inode;
-+	if (S_ISDIR(inode->i_mode))
-+		au_fset_wrdir(wr_dir_args.flags, ISDIR);
-+	/* plink or hi_wh() case */
-+	if (bstart != au_ibstart(inode))
-+		wr_dir_args.force_btgt = au_ibstart(inode);
-+	err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
-+	if (unlikely(err < 0))
-+		goto out_dentry;
-+	a->btgt = err;
-+	if (err != bstart)
-+		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);
-+	}
-+
-+	udba = au_opt_udba(dentry->d_sb);
-+	if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
-+		udba = AuOpt_UDBA_NONE;
-+	err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
-+	if (unlikely(err))
-+		goto out_parent;
-+
-+	a->h_path.dentry = au_h_dptr(dentry, bstart);
-+	a->h_inode = a->h_path.dentry->d_inode;
-+	mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
-+	sz = -1;
-+	if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
-+		sz = ia->ia_size;
-+
-+	h_file = NULL;
-+	hi_wh = NULL;
-+	if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
-+		hi_wh = au_hi_wh(inode, a->btgt);
-+		if (!hi_wh) {
-+			err = au_sio_cpup_wh(dentry, a->btgt, sz, /*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)) {
-+		h_file = au_h_open_pre(dentry, bstart);
-+		if (IS_ERR(h_file)) {
-+			err = PTR_ERR(h_file);
-+			h_file = NULL;
-+		} else
-+			err = au_sio_cpup_simple(dentry, a->btgt, sz,
-+						 AuCpup_DTIME);
-+		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:
-+	mutex_unlock(&a->h_inode->i_mutex);
-+	au_h_open_post(dentry, bstart, h_file);
-+	a->h_inode = a->h_path.dentry->d_inode;
-+	if (!err) {
-+		mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
-+		goto out; /* success */
-+	}
-+
-+	au_unpin(&a->pin);
-+ out_parent:
-+	if (parent) {
-+		di_write_unlock(parent);
-+		dput(parent);
-+	}
-+ out_dentry:
-+	di_write_unlock(dentry);
-+ out:
-+	return err;
-+}
-+
-+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
-+{
-+	int err;
-+	struct inode *inode;
-+	struct super_block *sb;
-+	struct file *file;
-+	struct au_icpup_args *a;
-+
-+	err = -ENOMEM;
-+	a = kzalloc(sizeof(*a), GFP_NOFS);
-+	if (unlikely(!a))
-+		goto out;
-+
-+	inode = dentry->d_inode;
-+	IMustLock(inode);
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+
-+	file = NULL;
-+	if (ia->ia_valid & ATTR_FILE) {
-+		/* currently ftruncate(2) only */
-+		file = ia->ia_file;
-+		fi_write_lock(file);
-+		ia->ia_file = au_h_fptr(file, au_fbstart(file));
-+	}
-+
-+	if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
-+		ia->ia_valid &= ~ATTR_MODE;
-+
-+	err = au_lock_and_icpup(dentry, ia, a);
-+	if (unlikely(err < 0))
-+		goto out_si;
-+	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.dentry, a->h_path.mnt,
-+					  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 */
-+			err = vmtruncate(inode, ia->ia_size);
-+			if (unlikely(err))
-+				goto out_unlock;
-+		}
-+
-+		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
-+		err = vfsub_notify_change(&a->h_path, ia);
-+	if (!err)
-+		au_cpup_attr_changeable(inode);
-+
-+ out_unlock:
-+	mutex_unlock(&a->h_inode->i_mutex);
-+	au_unpin(&a->pin);
-+	di_write_unlock(dentry);
-+ out_si:
-+	if (file) {
-+		fi_write_unlock(file);
-+		ia->ia_file = file;
-+		ia->ia_valid |= ATTR_FILE;
-+	}
-+	si_read_unlock(sb);
-+	kfree(a);
-+ out:
-+	return err;
-+}
-+
-+static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
-+{
-+	int err;
-+	struct inode *inode;
-+	struct dentry *parent;
-+
-+	err = 0;
-+	inode = dentry->d_inode;
-+	di_write_lock_child(dentry);
-+	if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
-+		parent = dget_parent(dentry);
-+		di_read_lock_parent(parent, AuLock_IR);
-+		/* returns a number of positive dentries */
-+		err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
-+		if (err >= 0)
-+			err = au_refresh_hinode(inode, dentry);
-+		di_read_unlock(parent, AuLock_IR);
-+		dput(parent);
-+	}
-+	di_downgrade_lock(dentry, AuLock_IR);
-+	if (unlikely(err))
-+		di_read_unlock(dentry, AuLock_IR);
-+
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
-+			     unsigned int nlink)
-+{
-+	inode->i_mode = st->mode;
-+	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)) {
-+		inode->i_nlink -= nlink;
-+		inode->i_nlink += st->nlink;
-+	}
-+
-+	spin_lock(&inode->i_lock);
-+	inode->i_blocks = st->blocks;
-+	i_size_write(inode, st->size);
-+	spin_unlock(&inode->i_lock);
-+}
-+
-+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
-+			struct dentry *dentry, struct kstat *st)
-+{
-+	int err;
-+	unsigned int mnt_flags;
-+	aufs_bindex_t bindex;
-+	unsigned char udba_none, positive;
-+	struct super_block *sb, *h_sb;
-+	struct inode *inode;
-+	struct vfsmount *h_mnt;
-+	struct dentry *h_dentry;
-+
-+	err = 0;
-+	sb = dentry->d_sb;
-+	inode = dentry->d_inode;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	mnt_flags = au_mntflags(sb);
-+	udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
-+
-+	/* support fstat(2) */
-+	if (!d_unhashed(dentry) && !udba_none) {
-+		unsigned int sigen = au_sigen(sb);
-+		if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
-+			di_read_lock_child(dentry, AuLock_IR);
-+		else {
-+			AuDebugOn(IS_ROOT(dentry));
-+			err = au_getattr_lock_reval(dentry, sigen);
-+			if (unlikely(err))
-+				goto out;
-+		}
-+	} else
-+		di_read_lock_child(dentry, AuLock_IR);
-+
-+	bindex = au_ibstart(inode);
-+	h_mnt = au_sbr_mnt(sb, bindex);
-+	h_sb = h_mnt->mnt_sb;
-+	if (!au_test_fs_bad_iattr(h_sb) && udba_none)
-+		goto out_fill; /* success */
-+
-+	h_dentry = NULL;
-+	if (au_dbstart(dentry) == bindex)
-+		h_dentry = dget(au_h_dptr(dentry, bindex));
-+	else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
-+		h_dentry = au_plink_lkup(inode, bindex);
-+		if (IS_ERR(h_dentry))
-+			goto out_fill; /* pretending success */
-+	}
-+	/* illegally overlapped or something */
-+	if (unlikely(!h_dentry))
-+		goto out_fill; /* pretending success */
-+
-+	positive = !!h_dentry->d_inode;
-+	if (positive)
-+		err = vfs_getattr(h_mnt, h_dentry, st);
-+	dput(h_dentry);
-+	if (!err) {
-+		if (positive)
-+			au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
-+		goto out_fill; /* success */
-+	}
-+	goto out_unlock;
-+
-+ out_fill:
-+	generic_fillattr(inode, st);
-+ out_unlock:
-+	di_read_unlock(dentry, AuLock_IR);
-+ out:
-+	si_read_unlock(sb);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
-+		      int bufsiz)
-+{
-+	int err;
-+	struct super_block *sb;
-+	struct dentry *h_dentry;
-+
-+	err = -EINVAL;
-+	h_dentry = au_h_dptr(dentry, bindex);
-+	if (unlikely(!h_dentry->d_inode->i_op->readlink))
-+		goto out;
-+
-+	err = security_inode_readlink(h_dentry);
-+	if (unlikely(err))
-+		goto out;
-+
-+	sb = dentry->d_sb;
-+	if (!au_test_ro(sb, bindex, dentry->d_inode)) {
-+		vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
-+		fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
-+	}
-+	err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
-+
-+ out:
-+	return err;
-+}
-+
-+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
-+{
-+	int err;
-+
-+	aufs_read_lock(dentry, AuLock_IR);
-+	err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
-+	aufs_read_unlock(dentry, AuLock_IR);
-+
-+	return err;
-+}
-+
-+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+	int err;
-+	char *buf;
-+	mm_segment_t old_fs;
-+
-+	err = -ENOMEM;
-+	buf = __getname_gfp(GFP_NOFS);
-+	if (unlikely(!buf))
-+		goto out;
-+
-+	aufs_read_lock(dentry, AuLock_IR);
-+	old_fs = get_fs();
-+	set_fs(KERNEL_DS);
-+	err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
-+			 PATH_MAX);
-+	set_fs(old_fs);
-+	aufs_read_unlock(dentry, AuLock_IR);
-+
-+	if (err >= 0) {
-+		buf[err] = 0;
-+		/* will be freed by put_link */
-+		nd_set_link(nd, buf);
-+		return NULL; /* success */
-+	}
-+	__putname(buf);
-+
-+ out:
-+	path_put(&nd->path);
-+	AuTraceErr(err);
-+	return ERR_PTR(err);
-+}
-+
-+static void aufs_put_link(struct dentry *dentry __maybe_unused,
-+			  struct nameidata *nd, void *cookie __maybe_unused)
-+{
-+	__putname(nd_get_link(nd));
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void aufs_truncate_range(struct inode *inode __maybe_unused,
-+				loff_t start __maybe_unused,
-+				loff_t end __maybe_unused)
-+{
-+	AuUnsupport();
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+struct inode_operations aufs_symlink_iop = {
-+	.permission	= aufs_permission,
-+	.setattr	= aufs_setattr,
-+	.getattr	= aufs_getattr,
-+	.readlink	= aufs_readlink,
-+	.follow_link	= aufs_follow_link,
-+	.put_link	= aufs_put_link
-+};
-+
-+struct inode_operations aufs_dir_iop = {
-+	.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,
-+	.setattr	= aufs_setattr,
-+	.getattr	= aufs_getattr
-+};
-+
-+struct inode_operations aufs_iop = {
-+	.permission	= aufs_permission,
-+	.setattr	= aufs_setattr,
-+	.getattr	= aufs_getattr,
-+	.truncate_range	= aufs_truncate_range
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_del.c \
                linux-2.6.33.1/fs/aufs/i_op_del.c
---- linux-2.6.33.1-vanilla/fs/aufs/i_op_del.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/i_op_del.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,472 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 bstart;
-+	struct super_block *sb;
-+
-+	sb = dentry->d_sb;
-+	bstart = au_dbstart(dentry);
-+	if (*bcpup < 0) {
-+		*bcpup = bstart;
-+		if (au_test_ro(sb, bstart, dentry->d_inode)) {
-+			err = AuWbrCopyup(au_sbi(sb), dentry);
-+			*bcpup = err;
-+			if (unlikely(err < 0))
-+				goto out;
-+		}
-+	} else
-+		AuDebugOn(bstart < *bcpup
-+			  || au_test_ro(sb, *bcpup, dentry->d_inode));
-+	AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
-+
-+	if (*bcpup != bstart) {
-+		err = au_cpup_dirs(dentry, *bcpup);
-+		if (unlikely(err))
-+			goto out;
-+		need_wh = 1;
-+	} else {
-+		aufs_bindex_t old_bend, new_bend, bdiropq = -1;
-+
-+		old_bend = au_dbend(dentry);
-+		if (isdir) {
-+			bdiropq = au_dbdiropq(dentry);
-+			au_set_dbdiropq(dentry, -1);
-+		}
-+		need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
-+					 /*nd*/NULL);
-+		err = need_wh;
-+		if (isdir)
-+			au_set_dbdiropq(dentry, bdiropq);
-+		if (unlikely(err < 0))
-+			goto out;
-+		new_bend = au_dbend(dentry);
-+		if (!need_wh && old_bend != new_bend) {
-+			au_set_h_dptr(dentry, new_bend, NULL);
-+			au_set_dbend(dentry, old_bend);
-+		}
-+	}
-+	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);
-+	h_inode = h_dentry->d_inode;
-+	if (dentry->d_inode) {
-+		err = -ENOENT;
-+		if (unlikely(!h_inode || !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(h_inode))
-+			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_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
-+		goto out;
-+
-+	h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
-+				   au_sbr(dentry->d_sb, bindex));
-+	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_dbstart(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;
-+
-+	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 */
-+	au_hn_free(au_hi(dentry->d_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 %.*s, b%d failed, %d. ignored\n",
-+			AuDLNPair(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 = dentry->d_inode;
-+	d_drop(dentry);
-+	inode->i_ctime = dir->i_ctime;
-+
-+	if (atomic_read(&dentry->d_count) == 1) {
-+		au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
-+		au_update_dbstart(dentry);
-+	}
-+	if (au_ibstart(dir) == bindex)
-+		au_cpup_attr_timesizes(dir);
-+	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 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, bwh)
-+	};
-+
-+	rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
-+	if (!rerr) {
-+		au_set_dbwh(dentry, bwh);
-+		au_dtime_revert(dt);
-+		return 0;
-+	}
-+
-+	AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
-+		AuDLNPair(dentry), err, rerr);
-+	return -EIO;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int aufs_unlink(struct inode *dir, struct dentry *dentry)
-+{
-+	int err;
-+	aufs_bindex_t bwh, bindex, bstart;
-+	struct au_dtime dt;
-+	struct au_pin pin;
-+	struct path h_path;
-+	struct inode *inode, *h_dir;
-+	struct dentry *parent, *wh_dentry;
-+
-+	IMustLock(dir);
-+	inode = dentry->d_inode;
-+	if (unlikely(!inode))
-+		return -ENOENT; /* possible? */
-+	IMustLock(inode);
-+
-+	aufs_read_lock(dentry, AuLock_DW);
-+	parent = dentry->d_parent; /* dir inode is locked */
-+	di_write_lock_parent(parent);
-+
-+	bstart = au_dbstart(dentry);
-+	bwh = au_dbwh(dentry);
-+	bindex = -1;
-+	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
-+	err = PTR_ERR(wh_dentry);
-+	if (IS_ERR(wh_dentry))
-+		goto out;
-+
-+	h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
-+	h_path.dentry = au_h_dptr(dentry, bstart);
-+	dget(h_path.dentry);
-+	if (bindex == bstart) {
-+		h_dir = au_pinned_h_dir(&pin);
-+		err = vfsub_unlink(h_dir, &h_path, /*force*/0);
-+	} else {
-+		/* dir inode is locked */
-+		h_dir = wh_dentry->d_parent->d_inode;
-+		IMustLock(h_dir);
-+		err = 0;
-+	}
-+
-+	if (!err) {
-+		drop_nlink(inode);
-+		epilog(dir, dentry, bindex);
-+
-+		/* update target timestamps */
-+		if (bindex == bstart) {
-+			vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
-+			inode->i_ctime = h_path.dentry->d_inode->i_ctime;
-+		} else
-+			/* todo: this timestamp may be reverted later */
-+			inode->i_ctime = h_dir->i_ctime;
-+		goto out_unlock; /* success */
-+	}
-+
-+	/* revert */
-+	if (wh_dentry) {
-+		int rerr;
-+
-+		rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
-+		if (rerr)
-+			err = rerr;
-+	}
-+
-+ out_unlock:
-+	au_unpin(&pin);
-+	dput(wh_dentry);
-+	dput(h_path.dentry);
-+ out:
-+	di_write_unlock(parent);
-+	aufs_read_unlock(dentry, AuLock_DW);
-+	return err;
-+}
-+
-+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
-+{
-+	int err, rmdir_later;
-+	aufs_bindex_t bwh, bindex, bstart;
-+	struct au_dtime dt;
-+	struct au_pin pin;
-+	struct inode *inode;
-+	struct dentry *parent, *wh_dentry, *h_dentry;
-+	struct au_whtmp_rmdir *args;
-+
-+	IMustLock(dir);
-+	inode = dentry->d_inode;
-+	err = -ENOENT; /* possible? */
-+	if (unlikely(!inode))
-+		goto out;
-+	IMustLock(inode);
-+
-+	aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
-+	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_args;
-+
-+	bstart = au_dbstart(dentry);
-+	bwh = au_dbwh(dentry);
-+	bindex = -1;
-+	wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
-+	err = PTR_ERR(wh_dentry);
-+	if (IS_ERR(wh_dentry))
-+		goto out_args;
-+
-+	h_dentry = au_h_dptr(dentry, bstart);
-+	dget(h_dentry);
-+	rmdir_later = 0;
-+	if (bindex == bstart) {
-+		err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
-+		if (err > 0) {
-+			rmdir_later = err;
-+			err = 0;
-+		}
-+	} else {
-+		/* stop monitoring */
-+		au_hn_free(au_hi(inode, bstart));
-+
-+		/* dir inode is locked */
-+		IMustLock(wh_dentry->d_parent->d_inode);
-+		err = 0;
-+	}
-+
-+	if (!err) {
-+		clear_nlink(inode);
-+		au_set_dbdiropq(dentry, -1);
-+		epilog(dir, dentry, bindex);
-+
-+		if (rmdir_later) {
-+			au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
-+			args = NULL;
-+		}
-+
-+		goto out_unpin; /* success */
-+	}
-+
-+	/* revert */
-+	AuLabel(revert);
-+	if (wh_dentry) {
-+		int rerr;
-+
-+		rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
-+		if (rerr)
-+			err = rerr;
-+	}
-+
-+ out_unpin:
-+	au_unpin(&pin);
-+	dput(wh_dentry);
-+	dput(h_dentry);
-+ out_args:
-+	di_write_unlock(parent);
-+	if (args)
-+		au_whtmp_rmdir_free(args);
-+ out_unlock:
-+	aufs_read_unlock(dentry, AuLock_DW);
-+ out:
-+	AuTraceErr(err);
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/i_op_ren.c \
                linux-2.6.33.1/fs/aufs/i_op_ren.c
---- linux-2.6.33.1-vanilla/fs/aufs/i_op_ren.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/i_op_ren.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,977 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 AuRen_CPUP	(1 << 7)
-+#define au_ftest_ren(flags, name)	((flags) & AuRen_##name)
-+#define au_fset_ren(flags, name)	{ (flags) |= AuRen_##name; }
-+#define au_fclr_ren(flags, name)	{ (flags) &= ~AuRen_##name; }
-+
-+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 bstart;
-+	} 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_bstart	sd[AuSRC].bstart
-+
-+#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_bstart	sd[AuDST].bstart
-+
-+	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;
-+
-+	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 happend.
-+ * 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);
-+	if (rerr)
-+		RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
-+}
-+
-+static void au_ren_rev_rename(int err, struct au_ren_args *a)
-+{
-+	int rerr;
-+
-+	a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
-+				       a->br, /*nd*/NULL);
-+	rerr = PTR_ERR(a->h_path.dentry);
-+	if (IS_ERR(a->h_path.dentry)) {
-+		RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
-+		return;
-+	}
-+
-+	rerr = vfsub_rename(a->dst_h_dir,
-+			    au_h_dptr(a->src_dentry, a->btgt),
-+			    a->src_h_dir, &a->h_path);
-+	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 %.*s", AuDLNPair(a->src_dentry));
-+}
-+
-+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
-+{
-+	int rerr;
-+
-+	a->h_path.dentry = a->dst_h_dentry;
-+	rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
-+	au_set_h_dptr(a->src_dentry, a->btgt, NULL);
-+	au_set_dbstart(a->src_dentry, a->src_bstart);
-+	if (rerr)
-+		RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
-+}
-+
-+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
-+{
-+	int rerr;
-+
-+	a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
-+				       a->br, /*nd*/NULL);
-+	rerr = PTR_ERR(a->h_path.dentry);
-+	if (IS_ERR(a->h_path.dentry)) {
-+		RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
-+		return;
-+	}
-+	if (a->h_path.dentry->d_inode) {
-+		d_drop(a->h_path.dentry);
-+		dput(a->h_path.dentry);
-+		return;
-+	}
-+
-+	rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
-+	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 %.*s", AuDLNPair(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);
-+	if (rerr)
-+		RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
-+}
-+
-+static void au_ren_rev_drop(struct au_ren_args *a)
-+{
-+	struct dentry *d, *h_d;
-+	int i;
-+	aufs_bindex_t bend, bindex;
-+
-+	for (i = 0; i < AuSrcDst; i++) {
-+		d = a->sd[i].dentry;
-+		d_drop(d);
-+		bend = au_dbend(d);
-+		for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
-+			h_d = au_h_dptr(d, bindex);
-+			if (h_d)
-+				d_drop(h_d);
-+		}
-+	}
-+
-+	au_update_dbstart(a->dst_dentry);
-+	if (a->thargs)
-+		d_drop(a->h_dst);
-+}
-+#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;
-+
-+	d = a->src_dentry;
-+	if (au_dbstart(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_dbstart(d) != a->btgt);
-+		err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
-+				   a->dst_h_dir, &a->h_path);
-+	} else {
-+		struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
-+		struct file *h_file;
-+
-+		au_fset_ren(a->flags, CPUP);
-+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+		au_set_dbstart(d, a->btgt);
-+		au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
-+		h_file = au_h_open_pre(d, a->src_bstart);
-+		if (IS_ERR(h_file)) {
-+			err = PTR_ERR(h_file);
-+			h_file = NULL;
-+		} else
-+			err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
-+						 !AuCpup_DTIME, a->dst_parent);
-+		mutex_unlock(h_mtx);
-+		au_h_open_post(d, a->src_bstart, h_file);
-+		if (!err) {
-+			d = a->dst_dentry;
-+			au_set_h_dptr(d, a->btgt, NULL);
-+			au_update_dbstart(d);
-+		} else {
-+			au_set_h_dptr(d, a->btgt, NULL);
-+			au_set_dbstart(d, a->src_bstart);
-+		}
-+	}
-+
-+	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_warning("failed removing whtmp dir %.*s (%d), "
-+				   "ignored.\n", AuDLNPair(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_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);
-+	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) && h_d->d_inode) {
-+		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_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 (!h_d->d_inode)
-+			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);
-+		if (unlikely(err))
-+			goto out_whtmp;
-+		a->dst_h_dentry = au_h_dptr(d, a->btgt);
-+	}
-+
-+	/* cpup src */
-+	if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
-+		struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
-+		struct file *h_file;
-+
-+		mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
-+		AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
-+		h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
-+		if (IS_ERR(h_file)) {
-+			err = PTR_ERR(h_file);
-+			h_file = NULL;
-+		} else
-+			err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
-+						 !AuCpup_DTIME);
-+		mutex_unlock(h_mtx);
-+		au_h_open_post(a->src_dentry, a->src_bstart, h_file);
-+		if (unlikely(err))
-+			goto out_whtmp;
-+	}
-+
-+	/* 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_dbend(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_dbstart(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 = a->h_path.dentry->d_inode->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 */
-+
-+	err = 0;
-+	goto out_success;
-+
-+ out_diropq:
-+	if (au_ftest_ren(a->flags, DIROPQ))
-+		au_ren_rev_diropq(err, a);
-+ out_rename:
-+	if (!au_ftest_ren(a->flags, CPUP))
-+		au_ren_rev_rename(err, a);
-+	else
-+		au_ren_rev_cpup(err, a);
-+ 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);
-+	au_ren_rev_drop(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 bstart;
-+
-+	bstart = au_dbstart(dentry);
-+	if (bstart != 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 (bstart == 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_dbstart(d, a->dst_bstart);
-+		err = may_rename_dstdir(d, &a->whlist);
-+		au_set_dbstart(d, a->btgt);
-+	}
-+	a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
-+	if (unlikely(err))
-+		goto out;
-+
-+	d = a->src_dentry;
-+	a->src_h_dentry = au_h_dptr(d, au_dbstart(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_bstart == 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_bstart != a->btgt)
-+		goto out;
-+
-+	err = -EIO;
-+	h_inode = a->dst_h_dentry->d_inode;
-+	isdir = !!au_ftest_ren(a->flags, ISDIR);
-+	if (!a->dst_dentry->d_inode) {
-+		if (unlikely(h_inode))
-+			goto out;
-+		err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
-+				 isdir);
-+	} else {
-+		if (unlikely(!h_inode || !h_inode->i_nlink))
-+			goto out;
-+		err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
-+				 isdir);
-+		if (unlikely(err))
-+			goto out;
-+		err = -ENOTEMPTY;
-+		if (unlikely(a->dst_h_dentry == a->h_trap))
-+			goto out;
-+		err = 0;
-+	}
-+
-+ 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)
-+{
-+	struct super_block *sb;
-+
-+	sb = a->dst_dentry->d_sb;
-+	if (au_ftest_ren(a->flags, MNT_WRITE))
-+		mnt_drop_write(a->br->br_mnt);
-+	vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
-+			    a->dst_h_parent, a->dst_hdir);
-+}
-+
-+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);
-+	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 != a->src_h_parent->d_inode
-+		     || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
-+		err = au_busy_or_stale();
-+	if (!err && au_dbstart(a->src_dentry) == a->btgt)
-+		err = au_h_verify(a->src_h_dentry, udba,
-+				  a->src_h_parent->d_inode, a->src_h_parent,
-+				  a->br);
-+	if (!err && au_dbstart(a->dst_dentry) == a->btgt)
-+		err = au_h_verify(a->dst_h_dentry, udba,
-+				  a->dst_h_parent->d_inode, a->dst_h_parent,
-+				  a->br);
-+	if (!err) {
-+		err = mnt_want_write(a->br->br_mnt);
-+		if (unlikely(err))
-+			goto out_unlock;
-+		au_fset_ren(a->flags, MNT_WRITE);
-+		goto out; /* success */
-+	}
-+
-+	err = au_busy_or_stale();
-+
-+ out_unlock:
-+	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);
-+		if (a->dst_inode) {
-+			clear_nlink(a->dst_inode);
-+			au_cpup_attr_timesizes(a->dst_inode);
-+		}
-+	}
-+	if (au_ibstart(dir) == a->btgt)
-+		au_cpup_attr_timesizes(dir);
-+
-+	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);
-+	if (au_ibstart(dir) == a->btgt)
-+		au_cpup_attr_timesizes(dir);
-+}
-+
-+static void au_ren_refresh(struct au_ren_args *a)
-+{
-+	aufs_bindex_t bend, bindex;
-+	struct dentry *d, *h_d;
-+	struct inode *i, *h_i;
-+	struct super_block *sb;
-+
-+	d = a->src_dentry;
-+	au_set_dbwh(d, -1);
-+	bend = au_dbend(d);
-+	for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
-+		h_d = au_h_dptr(d, bindex);
-+		if (h_d)
-+			au_set_h_dptr(d, bindex, NULL);
-+	}
-+	au_set_dbend(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 */
-+
-+	bend = au_ibend(i);
-+	for (bindex = a->btgt + 1; bindex <= bend; 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_ibend(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(parent->d_inode); /* 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_bstart, dst_bstart 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_bstart = au_dbstart(a->src_dentry);
-+	a->dst_bstart = au_dbstart(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_bstart;
-+	if (a->dst_inode && a->dst_bstart < a->src_bstart)
-+		wr_dir_args.force_btgt = a->dst_bstart;
-+	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 (a->dst_h_dentry->d_inode) {
-+		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 = &h_d->d_inode->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 = &h_d->d_inode->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;
-+	/* reduce stack space */
-+	struct au_ren_args *a;
-+
-+	AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_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 = a->src_dentry->d_inode;
-+	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 = a->dst_dentry->d_inode;
-+	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;
-+	if (S_ISDIR(a->src_inode->i_mode)) {
-+		au_fset_ren(a->flags, ISDIR);
-+		if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
-+			goto out_free;
-+		aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
-+					  AuLock_DIR | AuLock_FLUSH);
-+	} else
-+		aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
-+					  AuLock_FLUSH);
-+
-+	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_unlock;
-+	a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
-+	a->h_path.mnt = a->br->br_mnt;
-+
-+	/* 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_bstart == 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);
-+
-+	/* lock them all */
-+	err = au_ren_lock(a);
-+	if (unlikely(err))
-+		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);
-+ out_unlock:
-+	if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
-+		au_update_dbstart(a->dst_dentry);
-+		d_drop(a->dst_dentry);
-+	}
-+	if (!err)
-+		d_move(a->src_dentry, 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);
-+	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);
-+	kfree(a);
-+ out:
-+	AuTraceErr(err);
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/Kconfig linux-2.6.33.1/fs/aufs/Kconfig
---- linux-2.6.33.1-vanilla/fs/aufs/Kconfig	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/Kconfig	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,172 @@
-+config AUFS_FS
-+	tristate "Aufs (Advanced multi layered unification filesystem) support"
-+	depends on EXPERIMENTAL
-+	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_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.
-+	It will have a negative impact to the performance.
-+	See detail in aufs.5.
-+
-+if AUFS_HNOTIFY
-+choice
-+	prompt ""
-+	default AUFS_HFSNOTIFY
-+config AUFS_HFSNOTIFY
-+	bool "fsnotify"
-+	select FSNOTIFY
-+config AUFS_HINOTIFY
-+	bool "inotify (DEPRECATED)"
-+	depends on INOTIFY
-+endchoice
-+endif
-+
-+config AUFS_EXPORT
-+	bool "NFS-exportable aufs"
-+	depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && 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_RDU
-+	bool "Readdir in userspace"
-+	help
-+	If you have millions of files under a single aufs directory, and
-+	meet the out of memory, then enable this option and set
-+	environment variables for your readdir(3).
-+	See detail in aufs.5.
-+
-+config AUFS_SP_IATTR
-+	bool "Respect the attributes (mtime/ctime mainly) of special files"
-+	help
-+	When you write something to a special file, some attributes of it
-+	(mtime/ctime mainly) may be updated. Generally such updates are
-+	less important (actually some device drivers and NFS ignore
-+	it). But some applications (such like test program) requires
-+	such updates. If you need these updates, then enable this
-+	configuration which introduces some overhead.
-+	Currently this configuration handles FIFO only.
-+
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/loop.c linux-2.6.33.1/fs/aufs/loop.c
---- linux-2.6.33.1-vanilla/fs/aufs/loop.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/loop.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,55 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * support for loopback block device as a branch
-+ */
-+
-+#include <linux/loop.h>
-+#include "aufs.h"
-+
-+/*
-+ * test if two lower dentries have overlapping branches.
-+ */
-+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
-+			     struct dentry *h_d2)
-+{
-+	struct inode *h_inode;
-+	struct loop_device *l;
-+
-+	h_inode = h_d1->d_inode;
-+	if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
-+		return 0;
-+
-+	l = h_inode->i_sb->s_bdev->bd_disk->private_data;
-+	h_d1 = l->lo_backing_file->f_dentry;
-+	/* h_d1 can be local NFS. in this case aufs cannot detect the loop */
-+	if (unlikely(h_d1->d_sb == sb))
-+		return 1;
-+	return !!au_test_subdir(h_d1, h_d2);
-+}
-+
-+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
-+int au_test_loopback_kthread(void)
-+{
-+	const char c = current->comm[4];
-+
-+	return current->mm == NULL
-+	       && '0' <= c && c <= '9'
-+	       && strncmp(current->comm, "loop", 4) == 0;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/loop.h linux-2.6.33.1/fs/aufs/loop.h
---- linux-2.6.33.1-vanilla/fs/aufs/loop.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/loop.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,43 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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
-+/* loop.c */
-+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
-+			     struct dentry *h_d2);
-+int au_test_loopback_kthread(void);
-+#else
-+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
-+	   struct dentry *h_d1, struct dentry *h_d2)
-+AuStubInt0(au_test_loopback_kthread, void)
-+#endif /* BLK_DEV_LOOP */
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_LOOP_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/magic.mk linux-2.6.33.1/fs/aufs/magic.mk
---- linux-2.6.33.1-vanilla/fs/aufs/magic.mk	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/magic.mk	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,54 @@
-+
-+# defined in ${srctree}/fs/fuse/inode.c
-+# tristate
-+ifdef CONFIG_FUSE_FS
-+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
-+endif
-+
-+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
-+# tristate
-+ifdef CONFIG_OCFS2_FS
-+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
-+endif
-+
-+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
-+# tristate
-+ifdef CONFIG_OCFS2_FS_O2CB
-+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
-+endif
-+
-+# defined in ${srctree}/fs/cifs/cifsfs.c
-+# tristate
-+ifdef CONFIG_CIFS_FS
-+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
-+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/9p/v9fs.h
-+# tristate
-+ifdef CONFIG_9P_FS
-+ccflags-y += -DV9FS_MAGIC=0x01021997
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/Makefile linux-2.6.33.1/fs/aufs/Makefile
---- linux-2.6.33.1-vanilla/fs/aufs/Makefile	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/Makefile	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,37 @@
-+
-+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
-+ccflags-y += -D'pr_fmt(fmt)="aufs %s:%d:%s[%d]: " fmt, \
-+	__func__, __LINE__, current->comm, current->pid'
-+
-+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 plink.o wbr_policy.o \
-+	dinfo.o dentry.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 \
-+	ioctl.o
-+
-+# all are boolean
-+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_HINOTIFY) += hinotify.o
-+aufs-$(CONFIG_AUFS_EXPORT) += export.o
-+aufs-$(CONFIG_AUFS_POLL) += poll.o
-+aufs-$(CONFIG_AUFS_RDU) += rdu.o
-+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
-+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
-+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
-+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/module.c linux-2.6.33.1/fs/aufs/module.c
---- linux-2.6.33.1-vanilla/fs/aufs/module.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/module.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,166 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * module global variables and operations
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include "aufs.h"
-+
-+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
-+{
-+	if (new_sz <= nused)
-+		return p;
-+
-+	p = krealloc(p, new_sz, gfp);
-+	if (p)
-+		memset(p + nused, 0, new_sz - nused);
-+	return p;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * aufs caches
-+ */
-+struct kmem_cache *au_cachep[AuCache_Last];
-+static int __init au_cache_init(void)
-+{
-+	au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
-+	if (au_cachep[AuCache_DINFO])
-+		au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
-+	if (au_cachep[AuCache_ICNTNR])
-+		au_cachep[AuCache_FINFO] = AuCache(au_finfo);
-+	if (au_cachep[AuCache_FINFO])
-+		au_cachep[AuCache_VDIR] = AuCache(au_vdir);
-+	if (au_cachep[AuCache_VDIR])
-+		au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
-+	if (au_cachep[AuCache_DEHSTR])
-+		return 0;
-+
-+	return -ENOMEM;
-+}
-+
-+static void au_cache_fin(void)
-+{
-+	int i;
-+
-+	/* including AuCache_HNOTIFY */
-+	for (i = 0; i < AuCache_Last; i++)
-+		if (au_cachep[i]) {
-+			kmem_cache_destroy(au_cachep[i]);
-+			au_cachep[i] = NULL;
-+		}
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int au_dir_roflags;
-+
-+/*
-+ * functions for module interface.
-+ */
-+MODULE_LICENSE("GPL");
-+/* MODULE_LICENSE("GPL v2"); */
-+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users at lists.sourceforge.net>");
-+MODULE_DESCRIPTION(AUFS_NAME
-+	" -- Advanced multi layered unification filesystem");
-+MODULE_VERSION(AUFS_VERSION);
-+
-+/* this module parameter has no meaning when SYSFS is disabled */
-+int sysaufs_brs = 1;
-+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
-+module_param_named(brs, sysaufs_brs, int, 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)
-+{
-+	return seq_path(seq, path, au_esc_chars);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int __init aufs_init(void)
-+{
-+	int err, i;
-+	char *p;
-+
-+	p = au_esc_chars;
-+	for (i = 1; i <= ' '; i++)
-+		*p++ = i;
-+	*p++ = '\\';
-+	*p++ = '\x7f';
-+	*p = 0;
-+
-+	au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
-+
-+	sysaufs_brs_init();
-+	au_debug_init();
-+	err = sysaufs_init();
-+	if (unlikely(err))
-+		goto out;
-+	err = au_wkq_init();
-+	if (unlikely(err))
-+		goto out_sysaufs;
-+	err = au_hnotify_init();
-+	if (unlikely(err))
-+		goto out_wkq;
-+	err = au_sysrq_init();
-+	if (unlikely(err))
-+		goto out_hin;
-+	err = au_cache_init();
-+	if (unlikely(err))
-+		goto out_sysrq;
-+	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_wkq:
-+	au_wkq_fin();
-+ out_sysaufs:
-+	sysaufs_fin();
-+ out:
-+	return err;
-+}
-+
-+static void __exit aufs_exit(void)
-+{
-+	unregister_filesystem(&aufs_fs_type);
-+	au_cache_fin();
-+	au_sysrq_fin();
-+	au_hnotify_fin();
-+	au_wkq_fin();
-+	sysaufs_fin();
-+}
-+
-+module_init(aufs_init);
-+module_exit(aufs_exit);
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/module.h linux-2.6.33.1/fs/aufs/module.h
---- linux-2.6.33.1-vanilla/fs/aufs/module.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/module.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,78 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * module initialization and module-global
-+ */
-+
-+#ifndef __AUFS_MODULE_H__
-+#define __AUFS_MODULE_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/slab.h>
-+
-+struct path;
-+struct seq_file;
-+
-+/* module parameters */
-+extern int sysaufs_brs;
-+
-+/* ---------------------------------------------------------------------- */
-+
-+extern int au_dir_roflags;
-+
-+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
-+int au_seq_path(struct seq_file *seq, struct path *path);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* kmem cache */
-+enum {
-+	AuCache_DINFO,
-+	AuCache_ICNTNR,
-+	AuCache_FINFO,
-+	AuCache_VDIR,
-+	AuCache_DEHSTR,
-+#ifdef CONFIG_AUFS_HNOTIFY
-+	AuCache_HNOTIFY,
-+#endif
-+	AuCache_Last
-+};
-+
-+#define AuCache(type)	KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
-+
-+extern struct kmem_cache *au_cachep[];
-+
-+#define AuCacheFuncs(name, index) \
-+static inline struct au_##name *au_cache_alloc_##name(void) \
-+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
-+static inline void au_cache_free_##name(struct au_##name *p) \
-+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
-+
-+AuCacheFuncs(dinfo, DINFO);
-+AuCacheFuncs(icntnr, ICNTNR);
-+AuCacheFuncs(finfo, FINFO);
-+AuCacheFuncs(vdir, VDIR);
-+AuCacheFuncs(vdir_dehstr, DEHSTR);
-+#ifdef CONFIG_AUFS_HNOTIFY
-+AuCacheFuncs(hnotify, HNOTIFY);
-+#endif
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_MODULE_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/opts.c linux-2.6.33.1/fs/aufs/opts.c
---- linux-2.6.33.1-vanilla/fs/aufs/opts.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/opts.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,1565 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * mount options/flags
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/namei.h>
-+#include <linux/types.h> /* a distribution requires */
-+#include <linux/parser.h>
-+#include "aufs.h"
-+
-+/* ---------------------------------------------------------------------- */
-+
-+enum {
-+	Opt_br,
-+	Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
-+	Opt_idel, Opt_imod, Opt_ireorder,
-+	Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
-+	Opt_rdblk_def, Opt_rdhash_def,
-+	Opt_xino, Opt_zxino, 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_lock, Opt_unlock, */
-+	Opt_cmd, Opt_cmd_args,
-+	Opt_diropq_a, Opt_diropq_w,
-+	Opt_warn_perm, Opt_nowarn_perm,
-+	Opt_wbr_copyup, Opt_wbr_create,
-+	Opt_refrof, Opt_norefrof,
-+	Opt_verbose, Opt_noverbose,
-+	Opt_sum, Opt_nosum, Opt_wsum,
-+	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"},
-+
-+	{Opt_plink, "plink"},
-+	{Opt_noplink, "noplink"},
-+#ifdef CONFIG_AUFS_DEBUG
-+	{Opt_list_plink, "list_plink"},
-+#endif
-+
-+	{Opt_udba, "udba=%s"},
-+
-+	{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, "coo=%s"},
-+	{Opt_ignore_silent, "nodlgt"},
-+	{Opt_ignore_silent, "nodirperm1"},
-+	{Opt_ignore_silent, "clean_plink"},
-+
-+#ifdef CONFIG_AUFS_SHWH
-+	{Opt_shwh, "shwh"},
-+#endif
-+	{Opt_noshwh, "noshwh"},
-+
-+	{Opt_rendir, "rendir=%d"},
-+
-+	{Opt_refrof, "refrof"},
-+	{Opt_norefrof, "norefrof"},
-+
-+	{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"},
-+
-+	/* 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, struct match_token *token)
-+{
-+	while (token->pattern) {
-+		if (token->token == val)
-+			return token->pattern;
-+		token++;
-+	}
-+	BUG();
-+	return "??";
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static match_table_t brperms = {
-+	{AuBrPerm_RO, AUFS_BRPERM_RO},
-+	{AuBrPerm_RR, AUFS_BRPERM_RR},
-+	{AuBrPerm_RW, AUFS_BRPERM_RW},
-+
-+	{AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
-+	{AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
-+	{AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
-+
-+	{AuBrPerm_ROWH, "nfsro"},
-+	{AuBrPerm_RO, NULL}
-+};
-+
-+static int noinline_for_stack br_perm_val(char *perm)
-+{
-+	int val;
-+	substring_t args[MAX_OPT_ARGS];
-+
-+	val = match_token(perm, brperms, args);
-+	return val;
-+}
-+
-+const char *au_optstr_br_perm(int brperm)
-+{
-+	return au_parser_pattern(brperm, (void *)brperms);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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"},
-+#else
-+	{AuOpt_UDBA_HNOTIFY, "inotify"},
-+#endif
-+#endif
-+	{-1, NULL}
-+};
-+
-+static void au_warn_inotify(int val, char *str)
-+{
-+#ifdef CONFIG_AUFS_HINOTIFY
-+	if (val == AuOpt_UDBA_HNOTIFY
-+	    && !strcmp(str, "inotify"))
-+		AuWarn1("udba=inotify is deprecated, use udba=notify\n");
-+#endif
-+}
-+
-+static int noinline_for_stack udba_val(char *str)
-+{
-+	int val;
-+	substring_t args[MAX_OPT_ARGS];
-+
-+	val = match_token(str, udbalevel, args);
-+	au_warn_inotify(val, str);
-+	return val;
-+}
-+
-+const char *au_optstr_udba(int udba)
-+{
-+	return au_parser_pattern(udba, (void *)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"},
-+
-+	{AuWbrCreate_MFSRR, "mfsrr:%d"},
-+	{AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
-+	{AuWbrCreate_PMFS, "pmfs"},
-+	{AuWbrCreate_PMFSV, "pmfs:%d"},
-+
-+	{-1, NULL}
-+};
-+
-+/*
-+ * cf. linux/lib/parser.c and cmdline.c
-+ * gave up calling memparse() since it uses simple_strtoull() instead of
-+ * strict_...().
-+ */
-+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 = strict_strtoull(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)
-+		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:
-+		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:
-+		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_SECOND_DEF;
-+		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, (void *)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, (void *)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 %.*s}\n",
-+				  u.xino->path,
-+				  AuDLNPair(u.xino->file->f_dentry));
-+			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_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_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_refrof:
-+			AuLabel(refrof);
-+			break;
-+		case Opt_norefrof:
-+			AuLabel(norefrof);
-+			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:
-+				AuDbg("%llu watermark\n",
-+					  u.create->mfsrr_watermark);
-+				break;
-+			case AuWbrCreate_MFSRRV:
-+				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;
-+		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_Last;
-+	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_sbend(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_sbend(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_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 bend, 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);
-+	bend = au_sbend(sb);
-+	for (bindex = 0; bindex <= bend; 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_sbend(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], &opt->rdcache)))
-+				break;
-+			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_plink:
-+		case Opt_noplink:
-+		case Opt_list_plink:
-+		case Opt_diropq_a:
-+		case Opt_diropq_w:
-+		case Opt_warn_perm:
-+		case Opt_nowarn_perm:
-+		case Opt_refrof:
-+		case Opt_norefrof:
-+		case Opt_verbose:
-+		case Opt_noverbose:
-+		case Opt_sum:
-+		case Opt_nosum:
-+		case Opt_wsum:
-+		case Opt_rdblk_def:
-+		case Opt_rdhash_def:
-+			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_ignore:
-+			pr_warning("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;
-+		}
-+	}
-+
-+	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:
-+		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 = create->mfs_second * HZ;
-+		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);
-+		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_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_refrof:
-+		au_opt_set(sbinfo->si_mntflags, REFROF);
-+		break;
-+	case Opt_norefrof:
-+		au_opt_clr(sbinfo->si_mntflags, REFROF);
-+		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 = opt->rdcache * HZ;
-+		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_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;
-+
-+	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_sbend(sb) + 1;
-+		if (opt->add.bindex < 0)
-+			opt->add.bindex = 0;
-+		goto add;
-+	case Opt_prepend:
-+		opt->add.bindex = 0;
-+	add:
-+	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_DIR);
-+			if (au_br_whable(opt->add.perm))
-+				au_fset_opts(opts->flags, REFRESH_NONDIR);
-+		}
-+		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_DIR);
-+			au_fset_opts(opts->flags, REFRESH_NONDIR);
-+		}
-+		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_DIR);
-+				au_fset_opts(opts->flags, REFRESH_NONDIR);
-+			}
-+		}
-+		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 bend, 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_dentry->d_parent;
-+		root = sb->s_root;
-+		bend = au_sbend(sb);
-+		for (bindex = 0; bindex <= bend; 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;
-+	aufs_bindex_t bindex, bend;
-+	unsigned char do_plink, skip, do_free;
-+	struct au_branch *br;
-+	struct au_wbr *wbr;
-+	struct dentry *root;
-+	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_warning("first branch should be rw\n");
-+		if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
-+			pr_warning("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_warning("udba=*notify requires xino\n");
-+
-+	err = 0;
-+	root = sb->s_root;
-+	dir = sb->s_root->d_inode;
-+	do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
-+	bend = au_sbend(sb);
-+	for (bindex = 0; !err && bindex <= bend; bindex++) {
-+		skip = 0;
-+		h_dir = au_h_iptr(dir, bindex);
-+		br = au_sbr(sb, bindex);
-+		do_free = 0;
-+
-+		wbr = br->br_wbr;
-+		if (wbr)
-+			wbr_wh_read_lock(wbr);
-+
-+		switch (br->br_perm) {
-+		case AuBrPerm_RO:
-+		case AuBrPerm_ROWH:
-+		case AuBrPerm_RR:
-+		case AuBrPerm_RRWH:
-+			do_free = !!wbr;
-+			skip = (!wbr
-+				|| (!wbr->wbr_whbase
-+				    && !wbr->wbr_plink
-+				    && !wbr->wbr_orph));
-+			break;
-+
-+		case AuBrPerm_RWNoLinkWH:
-+			/* 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;
-+			}
-+			break;
-+
-+		case AuBrPerm_RW:
-+			/* 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;
-+			}
-+			break;
-+
-+		default:
-+			BUG();
-+		}
-+		if (wbr)
-+			wbr_wh_read_unlock(wbr);
-+
-+		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(au_h_dptr(root, bindex), br, sb);
-+		if (wbr)
-+			wbr_wh_write_unlock(wbr);
-+		au_hn_imtx_unlock(hdir);
-+
-+		if (!err && do_free) {
-+			kfree(wbr);
-+			br->br_wbr = NULL;
-+		}
-+	}
-+
-+	return err;
-+}
-+
-+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
-+{
-+	int err;
-+	unsigned int tmp;
-+	aufs_bindex_t bend;
-+	struct au_opt *opt;
-+	struct au_opt_xino *opt_xino, xino;
-+	struct au_sbinfo *sbinfo;
-+
-+	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;
-+
-+	bend = au_sbend(sb);
-+	if (unlikely(bend < 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 */
-+	sbinfo->si_mntflags &= ~AuOptMask_UDBA;
-+	sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
-+	if (au_opt_test(tmp, UDBA_HNOTIFY)) {
-+		struct inode *dir = sb->s_root->d_inode;
-+		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;
-+	struct inode *dir;
-+	struct au_opt_xino *opt_xino;
-+	struct au_opt *opt;
-+	struct au_sbinfo *sbinfo;
-+
-+	SiMustWriteLock(sb);
-+
-+	dir = sb->s_root->d_inode;
-+	sbinfo = au_sbi(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)
-+			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 */
-+
-+	rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
-+	if (unlikely(rerr && !err))
-+		err = rerr;
-+
-+	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_DIR)
-+	    && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
-+		au_fset_opts(opts->flags, REFRESH_DIR);
-+
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/opts.h linux-2.6.33.1/fs/aufs/opts.h
---- linux-2.6.33.1-vanilla/fs/aufs/opts.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/opts.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,196 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * mount options/flags
-+ */
-+
-+#ifndef __AUFS_OPTS_H__
-+#define __AUFS_OPTS_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/path.h>
-+#include <linux/aufs_type.h>
-+
-+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)	/* unimplemented */
-+#define AuOpt_REFROF		(1 << 8)	/* unimplemented */
-+#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 */
-+
-+#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)		{ ((flags) &= ~AuOpt_##name); }
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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_PMFS,	/* parent and mfs */
-+	AuWbrCreate_PMFSV,	/* parent and mfs with 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;
-+	};
-+};
-+
-+/* opts flags */
-+#define AuOpts_REMOUNT		1
-+#define AuOpts_REFRESH_DIR	(1 << 1)
-+#define AuOpts_REFRESH_NONDIR	(1 << 2)
-+#define AuOpts_TRUNC_XIB	(1 << 3)
-+#define au_ftest_opts(flags, name)	((flags) & AuOpts_##name)
-+#define au_fset_opts(flags, name)	{ (flags) |= AuOpts_##name; }
-+#define au_fclr_opts(flags, name)	{ (flags) &= ~AuOpts_##name; }
-+
-+struct au_opts {
-+	struct au_opt	*opt;
-+	int		max_opt;
-+
-+	unsigned int	given_udba;
-+	unsigned int	flags;
-+	unsigned long	sb_flags;
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
-+const char *au_optstr_br_perm(int brperm);
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/plink.c linux-2.6.33.1/fs/aufs/plink.c
---- linux-2.6.33.1-vanilla/fs/aufs/plink.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/plink.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,430 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * pseudo-link
-+ */
-+
-+#include "aufs.h"
-+
-+/*
-+ * during a user process maintains the pseudo-links,
-+ * prohibit adding a new plink and branch manipulation.
-+ */
-+void au_plink_maint_block(struct super_block *sb)
-+{
-+	struct au_sbinfo *sbi = au_sbi(sb);
-+
-+	SiMustAnyLock(sb);
-+
-+	/* gave up wake_up_bit() */
-+	wait_event(sbi->si_plink_wq, !sbi->si_plink_maint);
-+}
-+
-+void au_plink_maint_leave(struct file *file)
-+{
-+	struct au_sbinfo *sbinfo;
-+	int iam;
-+
-+	AuDebugOn(atomic_long_read(&file->f_count));
-+
-+	sbinfo = au_sbi(file->f_dentry->d_sb);
-+	spin_lock(&sbinfo->si_plink_maint_lock);
-+	iam = (sbinfo->si_plink_maint == file);
-+	if (iam)
-+		sbinfo->si_plink_maint = NULL;
-+	spin_unlock(&sbinfo->si_plink_maint_lock);
-+	if (iam)
-+		wake_up_all(&sbinfo->si_plink_wq);
-+}
-+
-+static int au_plink_maint_enter(struct file *file)
-+{
-+	int err;
-+	struct super_block *sb;
-+	struct au_sbinfo *sbinfo;
-+
-+	err = 0;
-+	sb = file->f_dentry->d_sb;
-+	sbinfo = au_sbi(sb);
-+	/* make sure i am the only one in this fs */
-+	si_write_lock(sb);
-+	/* spin_lock(&sbinfo->si_plink_maint_lock); */
-+	if (!sbinfo->si_plink_maint)
-+		sbinfo->si_plink_maint = file;
-+	else
-+		err = -EBUSY;
-+	/* spin_unlock(&sbinfo->si_plink_maint_lock); */
-+	si_write_unlock(sb);
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+struct pseudo_link {
-+	struct list_head list;
-+	struct inode *inode;
-+};
-+
-+#ifdef CONFIG_AUFS_DEBUG
-+void au_plink_list(struct super_block *sb)
-+{
-+	struct au_sbinfo *sbinfo;
-+	struct list_head *plink_list;
-+	struct pseudo_link *plink;
-+
-+	SiMustAnyLock(sb);
-+
-+	sbinfo = au_sbi(sb);
-+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
-+
-+	plink_list = &sbinfo->si_plink.head;
-+	spin_lock(&sbinfo->si_plink.spin);
-+	list_for_each_entry(plink, plink_list, list)
-+		AuDbg("%lu\n", plink->inode->i_ino);
-+	spin_unlock(&sbinfo->si_plink.spin);
-+}
-+#endif
-+
-+/* is the inode pseudo-linked? */
-+int au_plink_test(struct inode *inode)
-+{
-+	int found;
-+	struct au_sbinfo *sbinfo;
-+	struct list_head *plink_list;
-+	struct pseudo_link *plink;
-+
-+	sbinfo = au_sbi(inode->i_sb);
-+	AuRwMustAnyLock(&sbinfo->si_rwsem);
-+	AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
-+
-+	found = 0;
-+	plink_list = &sbinfo->si_plink.head;
-+	spin_lock(&sbinfo->si_plink.spin);
-+	list_for_each_entry(plink, plink_list, list)
-+		if (plink->inode == inode) {
-+			found = 1;
-+			break;
-+		}
-+	spin_unlock(&sbinfo->si_plink.spin);
-+	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;
-+}
-+
-+/* 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;
-+	struct inode *h_dir;
-+	char a[PLINK_NAME_LEN];
-+	struct qstr tgtname = {
-+		.name	= a
-+	};
-+
-+	br = au_sbr(inode->i_sb, bindex);
-+	h_parent = br->br_wbr->wbr_plink;
-+	h_dir = h_parent->d_inode;
-+	tgtname.len = plink_name(a, sizeof(a), inode, bindex);
-+
-+	/* always superio. */
-+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
-+	h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
-+	mutex_unlock(&h_dir->i_mutex);
-+	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 = br->br_mnt
-+	};
-+	struct inode *h_dir;
-+
-+	h_dir = h_parent->d_inode;
-+ again:
-+	h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
-+	err = PTR_ERR(h_path.dentry);
-+	if (IS_ERR(h_path.dentry))
-+		goto out;
-+
-+	err = 0;
-+	/* wh.plink dir is not monitored */
-+	if (h_path.dentry->d_inode
-+	    && h_path.dentry->d_inode != h_dentry->d_inode) {
-+		err = vfsub_unlink(h_dir, &h_path, /*force*/0);
-+		dput(h_path.dentry);
-+		h_path.dentry = NULL;
-+		if (!err)
-+			goto again;
-+	}
-+	if (!err && !h_path.dentry->d_inode)
-+		err = vfsub_link(h_dentry, h_dir, &h_path);
-+	dput(h_path.dentry);
-+
-+ out:
-+	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;
-+	struct inode *h_dir;
-+	char a[PLINK_NAME_LEN];
-+	struct qstr tgtname = {
-+		.name = a
-+	};
-+
-+	wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
-+	h_parent = wbr->wbr_plink;
-+	h_dir = h_parent->d_inode;
-+	tgtname.len = plink_name(a, sizeof(a), inode, bindex);
-+
-+	/* always superio. */
-+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
-+	if (!au_test_wkq(current)) {
-+		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);
-+	mutex_unlock(&h_dir->i_mutex);
-+
-+	return err;
-+}
-+
-+/* free a single plink */
-+static void do_put_plink(struct pseudo_link *plink, int do_del)
-+{
-+	iput(plink->inode);
-+	if (do_del)
-+		list_del(&plink->list);
-+	kfree(plink);
-+}
-+
-+/*
-+ * 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 list_head *plink_list;
-+	struct pseudo_link *plink;
-+	int found, err, cnt;
-+
-+	sb = inode->i_sb;
-+	sbinfo = au_sbi(sb);
-+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
-+
-+	err = 0;
-+	cnt = 0;
-+	found = 0;
-+	plink_list = &sbinfo->si_plink.head;
-+	spin_lock(&sbinfo->si_plink.spin);
-+	list_for_each_entry(plink, plink_list, list) {
-+		cnt++;
-+		if (plink->inode == inode) {
-+			found = 1;
-+			break;
-+		}
-+	}
-+	if (found) {
-+		spin_unlock(&sbinfo->si_plink.spin);
-+		return;
-+	}
-+
-+	plink = NULL;
-+	if (!found) {
-+		plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
-+		if (plink) {
-+			plink->inode = au_igrab(inode);
-+			list_add(&plink->list, plink_list);
-+			cnt++;
-+		} else
-+			err = -ENOMEM;
-+	}
-+	spin_unlock(&sbinfo->si_plink.spin);
-+
-+	if (!err) {
-+		au_plink_maint_block(sb);
-+		err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
-+	}
-+
-+	if (unlikely(cnt > AUFS_PLINK_WARN))
-+		AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
-+	if (unlikely(err)) {
-+		pr_warning("err %d, damaged pseudo link.\n", err);
-+		if (!found && plink)
-+			do_put_plink(plink, /*do_del*/1);
-+	}
-+}
-+
-+/* free all plinks */
-+void au_plink_put(struct super_block *sb)
-+{
-+	struct au_sbinfo *sbinfo;
-+	struct list_head *plink_list;
-+	struct pseudo_link *plink, *tmp;
-+
-+	SiMustWriteLock(sb);
-+
-+	sbinfo = au_sbi(sb);
-+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
-+
-+	plink_list = &sbinfo->si_plink.head;
-+	/* no spin_lock since sbinfo is write-locked */
-+	list_for_each_entry_safe(plink, tmp, plink_list, list)
-+		do_put_plink(plink, 0);
-+	INIT_LIST_HEAD(plink_list);
-+}
-+
-+/* 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 list_head *plink_list;
-+	struct pseudo_link *plink, *tmp;
-+	struct inode *inode;
-+	aufs_bindex_t bstart, bend, bindex;
-+	unsigned char do_put;
-+
-+	SiMustWriteLock(sb);
-+
-+	sbinfo = au_sbi(sb);
-+	AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
-+
-+	plink_list = &sbinfo->si_plink.head;
-+	/* no spin_lock since sbinfo is write-locked */
-+	list_for_each_entry_safe(plink, tmp, plink_list, list) {
-+		do_put = 0;
-+		inode = au_igrab(plink->inode);
-+		ii_write_lock_child(inode);
-+		bstart = au_ibstart(inode);
-+		bend = au_ibend(inode);
-+		if (bstart >= 0) {
-+			for (bindex = bstart; bindex <= bend; 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;
-+			}
-+		} else
-+			do_put_plink(plink, 1);
-+
-+		if (do_put) {
-+			for (bindex = bstart; bindex <= bend; bindex++)
-+				if (au_h_iptr(inode, bindex)) {
-+					do_put = 0;
-+					break;
-+				}
-+			if (do_put)
-+				do_put_plink(plink, 1);
-+		}
-+		ii_write_unlock(inode);
-+		iput(inode);
-+	}
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+long au_plink_ioctl(struct file *file, unsigned int cmd)
-+{
-+	long err;
-+	struct super_block *sb;
-+	struct au_sbinfo *sbinfo;
-+
-+	err = -EACCES;
-+	if (!capable(CAP_SYS_ADMIN))
-+		goto out;
-+
-+	err = 0;
-+	sb = file->f_dentry->d_sb;
-+	sbinfo = au_sbi(sb);
-+	switch (cmd) {
-+	case AUFS_CTL_PLINK_MAINT:
-+		/*
-+		 * pseudo-link maintenance mode,
-+		 * cleared by aufs_release_dir()
-+		 */
-+		err = au_plink_maint_enter(file);
-+		break;
-+	case AUFS_CTL_PLINK_CLEAN:
-+		aufs_write_lock(sb->s_root);
-+		if (au_opt_test(sbinfo->si_mntflags, PLINK))
-+			au_plink_put(sb);
-+		aufs_write_unlock(sb->s_root);
-+		break;
-+	default:
-+		/* err = -ENOTTY; */
-+		err = -EINVAL;
-+	}
-+ out:
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/poll.c linux-2.6.33.1/fs/aufs/poll.c
---- linux-2.6.33.1-vanilla/fs/aufs/poll.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/poll.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,56 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * 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 dentry *dentry;
-+	struct super_block *sb;
-+
-+	/* We should pretend an error happened. */
-+	mask = POLLERR /* | POLLIN | POLLOUT */;
-+	dentry = file->f_dentry;
-+	sb = dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
-+	if (unlikely(err))
-+		goto out;
-+
-+	/* it is not an error if h_file has no operation */
-+	mask = DEFAULT_POLLMASK;
-+	h_file = au_h_fptr(file, au_fbstart(file));
-+	if (h_file->f_op && h_file->f_op->poll)
-+		mask = h_file->f_op->poll(h_file, wait);
-+
-+	di_read_unlock(dentry, AuLock_IR);
-+	fi_read_unlock(file);
-+
-+ out:
-+	si_read_unlock(sb);
-+	AuTraceErr((int)mask);
-+	return mask;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/rdu.c linux-2.6.33.1/fs/aufs/rdu.c
---- linux-2.6.33.1-vanilla/fs/aufs/rdu.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/rdu.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,330 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * readdir in userspace.
-+ */
-+
-+#include <linux/fs_stack.h>
-+#include <linux/security.h>
-+#include <linux/uaccess.h>
-+#include <linux/aufs_type.h>
-+#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)	{ (flags) |= AuRdu_##name; }
-+#define au_fclr_rdu(flags, name)	{ (flags) &= ~AuRdu_##name; }
-+
-+struct au_rdu_arg {
-+	struct aufs_rdu			*rdu;
-+	union au_rdu_ent_ul		ent;
-+	unsigned long			end;
-+
-+	struct super_block		*sb;
-+	int				err;
-+};
-+
-+static int au_rdu_fill(void *__arg, const char *name, int nlen,
-+		       loff_t offset, u64 h_ino, unsigned int d_type)
-+{
-+	int err, len;
-+	struct au_rdu_arg *arg = __arg;
-+	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;
-+
-+		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;
-+
-+	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_readdir(h_file, au_rdu_fill, arg);
-+		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 bend;
-+	struct au_rdu_arg arg;
-+	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 || !file->f_op->readdir))
-+		goto out;
-+
-+	err = security_file_permission(file, MAY_READ);
-+	AuTraceErr(err);
-+	if (unlikely(err))
-+		goto out;
-+
-+	dentry = file->f_dentry;
-+	inode = dentry->d_inode;
-+#if 1
-+	mutex_lock(&inode->i_mutex);
-+#else
-+	err = mutex_lock_killable(&inode->i_mutex);
-+	AuTraceErr(err);
-+	if (unlikely(err))
-+		goto out;
-+#endif
-+	err = -ENOENT;
-+	if (unlikely(IS_DEADDIR(inode)))
-+		goto out_mtx;
-+
-+	arg.sb = inode->i_sb;
-+	si_read_lock(arg.sb, AuLock_FLUSH);
-+	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);
-+	}
-+	bend = au_fbstart(file);
-+	if (cookie->bindex < bend)
-+		cookie->bindex = bend;
-+	bend = au_fbend(file);
-+	/* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
-+	for (; !err && cookie->bindex <= bend;
-+	     cookie->bindex++, cookie->h_pos = 0) {
-+		h_file = au_h_fptr(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_ibstart(inode)));
-+	ii_read_unlock(inode);
-+
-+ out_unlock:
-+	fi_read_unlock(file);
-+	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_dentry->d_sb;
-+	si_read_lock(sb, AuLock_FLUSH);
-+	while (nent-- > 0) {
-+		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) | %u | %llu, %u, %u | "
-+	      "%llu, b%d, 0x%x, g%u}\n",
-+	      rdu->sz, rdu->ent.e, rdu->verify[0], rdu->verify[1],
-+	      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)
-+	    && rdu->verify[AufsCtlRduV_SZ_PTR] == sizeof(rdu))
-+		return 0;
-+
-+	AuDbg("%u:%u, %u:%u\n",
-+	      rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu),
-+	      rdu->verify[AufsCtlRduV_SZ_PTR], (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;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/rwsem.h linux-2.6.33.1/fs/aufs/rwsem.h
---- linux-2.6.33.1-vanilla/fs/aufs/rwsem.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/rwsem.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,187 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * simple read-write semaphore wrappers
-+ */
-+
-+#ifndef __AUFS_RWSEM_H__
-+#define __AUFS_RWSEM_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/rwsem.h>
-+#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_AUFS_DEBUG
-+#define AuDbgCntInit(rw) do { \
-+	atomic_set(&(rw)->rcnt, 0); \
-+	atomic_set(&(rw)->wcnt, 0); \
-+	smp_mb(); /* atomic set */ \
-+} while (0)
-+
-+#define AuDbgRcntInc(rw)	atomic_inc_return(&(rw)->rcnt)
-+#define AuDbgRcntDec(rw)	WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
-+#define AuDbgWcntInc(rw)	WARN_ON(atomic_inc_return(&(rw)->wcnt) > 1)
-+#define AuDbgWcntDec(rw)	WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
-+#else
-+#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(!list_empty(&(rw)->rwsem.wait_list))
-+/* rwsem_is_locked() is unusable */
-+#define AuRwMustReadLock(rw)	AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
-+#define AuRwMustWriteLock(rw)	AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
-+#define AuRwMustAnyLock(rw)	AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
-+					&& atomic_read(&(rw)->wcnt) <= 0)
-+#define AuRwDestroy(rw)		AuDebugOn(atomic_read(&(rw)->rcnt) \
-+					|| atomic_read(&(rw)->wcnt))
-+
-+static inline void au_rw_init(struct au_rwsem *rw)
-+{
-+	AuDbgCntInit(rw);
-+	init_rwsem(&rw->rwsem);
-+}
-+
-+static inline void au_rw_init_wlock(struct au_rwsem *rw)
-+{
-+	au_rw_init(rw);
-+	down_write(&rw->rwsem);
-+	AuDbgWcntInc(rw);
-+}
-+
-+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
-+					   unsigned int lsc)
-+{
-+	au_rw_init(rw);
-+	down_write_nested(&rw->rwsem, lsc);
-+	AuDbgWcntInc(rw);
-+}
-+
-+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 = down_read_trylock(&rw->rwsem);
-+	if (ret)
-+		AuDbgRcntInc(rw);
-+	return ret;
-+}
-+
-+static inline int au_rw_write_trylock(struct au_rwsem *rw)
-+{
-+	int ret = down_write_trylock(&rw->rwsem);
-+	if (ret)
-+		AuDbgWcntInc(rw);
-+	return ret;
-+}
-+
-+#undef AuDbgCntInit
-+#undef AuDbgRcntInc
-+#undef AuDbgRcntDec
-+#undef AuDbgWcntInc
-+#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 -Nur linux-2.6.33.1-vanilla/fs/aufs/sbinfo.c linux-2.6.33.1/fs/aufs/sbinfo.c
---- linux-2.6.33.1-vanilla/fs/aufs/sbinfo.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/sbinfo.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,202 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * superblock private data
-+ */
-+
-+#include "aufs.h"
-+
-+/*
-+ * they are necessary regardless sysfs is disabled.
-+ */
-+void au_si_free(struct kobject *kobj)
-+{
-+	struct au_sbinfo *sbinfo;
-+	struct super_block *sb;
-+
-+	sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
-+	AuDebugOn(!list_empty(&sbinfo->si_plink.head));
-+	AuDebugOn(sbinfo->si_plink_maint);
-+
-+	sb = sbinfo->si_sb;
-+	si_write_lock(sb);
-+	au_xino_clr(sb);
-+	au_br_free(sbinfo);
-+	kfree(sbinfo->si_branch);
-+	mutex_destroy(&sbinfo->si_xib_mtx);
-+	si_write_unlock(sb);
-+	AuRwDestroy(&sbinfo->si_rwsem);
-+
-+	kfree(sbinfo);
-+}
-+
-+int au_si_alloc(struct super_block *sb)
-+{
-+	int err;
-+	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);
-+	sbinfo->si_bend = -1;
-+
-+	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;
-+
-+	sbinfo->si_mntflags = AuOpt_Def;
-+
-+	mutex_init(&sbinfo->si_xib_mtx);
-+	sbinfo->si_xino_brid = -1;
-+	/* leave si_xib_last_pindex and si_xib_next_bit */
-+
-+	sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
-+	sbinfo->si_rdblk = AUFS_RDBLK_DEF;
-+	sbinfo->si_rdhash = AUFS_RDHASH_DEF;
-+	sbinfo->si_dirwh = AUFS_DIRWH_DEF;
-+
-+	au_spl_init(&sbinfo->si_plink);
-+	init_waitqueue_head(&sbinfo->si_plink_wq);
-+	spin_lock_init(&sbinfo->si_plink_maint_lock);
-+
-+	/* leave other members for sysaufs and si_mnt. */
-+	sbinfo->si_sb = sb;
-+	sb->s_fs_info = sbinfo;
-+	au_debug_sbinfo_init(sbinfo);
-+	return 0; /* success */
-+
-+ out_br:
-+	kfree(sbinfo->si_branch);
-+ out_sbinfo:
-+	kfree(sbinfo);
-+ out:
-+	return err;
-+}
-+
-+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
-+{
-+	int err, sz;
-+	struct au_branch **brp;
-+
-+	AuRwMustWriteLock(&sbinfo->si_rwsem);
-+
-+	err = -ENOMEM;
-+	sz = sizeof(*brp) * (sbinfo->si_bend + 1);
-+	if (unlikely(!sz))
-+		sz = sizeof(*brp);
-+	brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
-+	if (brp) {
-+		sbinfo->si_branch = brp;
-+		err = 0;
-+	}
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+unsigned int au_sigen_inc(struct super_block *sb)
-+{
-+	unsigned int gen;
-+
-+	SiMustWriteLock(sb);
-+
-+	gen = ++au_sbi(sb)->si_generation;
-+	au_update_digen(sb->s_root);
-+	au_update_iigen(sb->s_root->d_inode);
-+	sb->s_root->d_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;
-+		if (br_id && au_br_index(sb, br_id) < 0)
-+			return br_id;
-+	}
-+
-+	return -1;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* dentry and super_block lock. call at entry point */
-+void aufs_read_lock(struct dentry *dentry, int flags)
-+{
-+	si_read_lock(dentry->d_sb, flags);
-+	if (au_ftest_lock(flags, DW))
-+		di_write_lock_child(dentry);
-+	else
-+		di_read_lock_child(dentry, flags);
-+}
-+
-+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);
-+	di_write_lock_child(dentry);
-+}
-+
-+void aufs_write_unlock(struct dentry *dentry)
-+{
-+	di_write_unlock(dentry);
-+	si_write_unlock(dentry->d_sb);
-+}
-+
-+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
-+{
-+	si_read_lock(d1->d_sb, flags);
-+	di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
-+}
-+
-+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
-+{
-+	di_write_unlock2(d1, d2);
-+	si_read_unlock(d1->d_sb);
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/spl.h linux-2.6.33.1/fs/aufs/spl.h
---- linux-2.6.33.1-vanilla/fs/aufs/spl.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/spl.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,57 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * simple list protected by a spinlock
-+ */
-+
-+#ifndef __AUFS_SPL_H__
-+#define __AUFS_SPL_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/spinlock.h>
-+#include <linux/list.h>
-+
-+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);
-+}
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_SPL_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/super.c linux-2.6.33.1/fs/aufs/super.c
---- linux-2.6.33.1-vanilla/fs/aufs/super.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/super.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,838 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * mount and super_block operations
-+ */
-+
-+#include <linux/buffer_head.h>
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include <linux/statfs.h>
-+#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) {
-+		inode_init_once(&c->vfs_inode);
-+		c->vfs_inode.i_version = 1; /* sigen(sb); */
-+		c->iinfo.ii_hinode = NULL;
-+		return &c->vfs_inode;
-+	}
-+	return NULL;
-+}
-+
-+static void aufs_destroy_inode(struct inode *inode)
-+{
-+	au_iinfo_fin(inode);
-+	au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
-+}
-+
-+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
-+{
-+	struct inode *inode;
-+	int err;
-+
-+	inode = iget_locked(sb, ino);
-+	if (unlikely(!inode)) {
-+		inode = ERR_PTR(-ENOMEM);
-+		goto out;
-+	}
-+	if (!(inode->i_state & I_NEW))
-+		goto out;
-+
-+	err = au_xigen_new(inode);
-+	if (!err)
-+		err = au_iinfo_init(inode);
-+	if (!err)
-+		inode->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, bend;
-+	struct path path;
-+	struct au_hdentry *hd;
-+	struct au_branch *br;
-+
-+	err = 0;
-+	bend = au_sbend(sb);
-+	hd = au_di(sb->s_root)->di_hdentry;
-+	for (bindex = 0; !err && bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		path.mnt = br->br_mnt;
-+		path.dentry = hd[bindex].hd_dentry;
-+		err = au_seq_path(seq, &path);
-+		if (err > 0)
-+			err = seq_printf(seq, "=%s",
-+					 au_optstr_br_perm(br->br_perm));
-+		if (!err && bindex != bend)
-+			err = seq_putc(seq, ':');
-+	}
-+
-+	return err;
-+}
-+
-+static void au_show_wbr_create(struct seq_file *m, int v,
-+			       struct au_sbinfo *sbinfo)
-+{
-+	const char *pat;
-+
-+	AuRwMustAnyLock(&sbinfo->si_rwsem);
-+
-+	seq_printf(m, ",create=");
-+	pat = au_optstr_wbr_create(v);
-+	switch (v) {
-+	case AuWbrCreate_TDP:
-+	case AuWbrCreate_RR:
-+	case AuWbrCreate_MFS:
-+	case AuWbrCreate_PMFS:
-+		seq_printf(m, pat);
-+		break;
-+	case AuWbrCreate_MFSV:
-+		seq_printf(m, /*pat*/"mfs:%lu",
-+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
-+		break;
-+	case AuWbrCreate_PMFSV:
-+		seq_printf(m, /*pat*/"pmfs:%lu",
-+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
-+		break;
-+	case AuWbrCreate_MFSRR:
-+		seq_printf(m, /*pat*/"mfsrr:%llu",
-+			   sbinfo->si_wbr_mfs.mfsrr_watermark);
-+		break;
-+	case AuWbrCreate_MFSRRV:
-+		seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
-+			   sbinfo->si_wbr_mfs.mfsrr_watermark,
-+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
-+		break;
-+	}
-+}
-+
-+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
-+{
-+#ifdef CONFIG_SYSFS
-+	return 0;
-+#else
-+	int err;
-+	const int len = sizeof(AUFS_XINO_FNAME) - 1;
-+	aufs_bindex_t bindex, brid;
-+	struct super_block *sb;
-+	struct qstr *name;
-+	struct file *f;
-+	struct dentry *d, *h_root;
-+
-+	AuRwMustAnyLock(&sbinfo->si_rwsem);
-+
-+	err = 0;
-+	sb = mnt->mnt_sb;
-+	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_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
-+	}
-+	d = f->f_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 vfsmount *mnt)
-+{
-+	int err, n;
-+	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)
-+
-+	/* lock free root dinfo */
-+	sb = mnt->mnt_sb;
-+	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, mnt);
-+		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(DIRPERM1, dirperm1); */
-+	/* AuBool(REFROF, refrof); */
-+
-+	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);
-+
-+	n = sbinfo->si_rdcache / HZ;
-+	AuUInt(RDCACHE, rdcache, n);
-+
-+	AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
-+	AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
-+
-+	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 int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
-+{
-+	int err;
-+	u64 blocks, bfree, bavail, files, ffree;
-+	aufs_bindex_t bend, bindex, i;
-+	unsigned char shared;
-+	struct vfsmount *h_mnt;
-+	struct super_block *h_sb;
-+
-+	blocks = 0;
-+	bfree = 0;
-+	bavail = 0;
-+	files = 0;
-+	ffree = 0;
-+
-+	err = 0;
-+	bend = au_sbend(sb);
-+	for (bindex = bend; bindex >= 0; bindex--) {
-+		h_mnt = au_sbr_mnt(sb, bindex);
-+		h_sb = h_mnt->mnt_sb;
-+		shared = 0;
-+		for (i = bindex + 1; !shared && i <= bend; i++)
-+			shared = (au_sbr_sb(sb, i) == h_sb);
-+		if (shared)
-+			continue;
-+
-+		/* sb->s_root for NFS is unreliable */
-+		err = vfs_statfs(h_mnt->mnt_root, buf);
-+		if (unlikely(err))
-+			goto out;
-+
-+		blocks = au_add_till_max(blocks, buf->f_blocks);
-+		bfree = au_add_till_max(bfree, buf->f_bfree);
-+		bavail = au_add_till_max(bavail, buf->f_bavail);
-+		files = au_add_till_max(files, buf->f_files);
-+		ffree = au_add_till_max(ffree, buf->f_ffree);
-+	}
-+
-+	buf->f_blocks = blocks;
-+	buf->f_bfree = bfree;
-+	buf->f_bavail = bavail;
-+	buf->f_files = files;
-+	buf->f_ffree = ffree;
-+
-+ out:
-+	return err;
-+}
-+
-+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
-+{
-+	int err;
-+	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 */
-+		err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, 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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * this IS NOT for super_operations.
-+ * I guess it will be reverted someday.
-+ */
-+static void aufs_umount_begin(struct super_block *sb)
-+{
-+	struct au_sbinfo *sbinfo;
-+
-+	sbinfo = au_sbi(sb);
-+	if (!sbinfo)
-+		return;
-+
-+	si_write_lock(sb);
-+	if (au_opt_test(au_mntflags(sb), PLINK))
-+		au_plink_put(sb);
-+	if (sbinfo->si_wbr_create_ops->fin)
-+		sbinfo->si_wbr_create_ops->fin(sb);
-+	si_write_unlock(sb);
-+}
-+
-+/* 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;
-+
-+	aufs_umount_begin(sb);
-+	dbgaufs_si_fin(sbinfo);
-+	kobject_put(&sbinfo->si_kobj);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/*
-+ * refresh dentry and inode at remount time.
-+ */
-+static int do_refresh(struct dentry *dentry, mode_t type,
-+		      unsigned int dir_flags)
-+{
-+	int err;
-+	struct dentry *parent;
-+
-+	di_write_lock_child(dentry);
-+	parent = dget_parent(dentry);
-+	di_read_lock_parent(parent, AuLock_IR);
-+
-+	/* returns the number of positive dentries */
-+	err = au_refresh_hdentry(dentry, type);
-+	if (err >= 0) {
-+		struct inode *inode = dentry->d_inode;
-+		err = au_refresh_hinode(inode, dentry);
-+		if (!err && type == S_IFDIR)
-+			au_hn_reset(inode, dir_flags);
-+	}
-+	if (unlikely(err))
-+		pr_err("unrecoverable error %d, %.*s\n",
-+		       err, AuDLNPair(dentry));
-+
-+	di_read_unlock(parent, AuLock_IR);
-+	dput(parent);
-+	di_write_unlock(dentry);
-+
-+	return err;
-+}
-+
-+static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
-+{
-+	return S_ISDIR(dentry->d_inode->i_mode);
-+}
-+
-+/* gave up consolidating with refresh_nondir() */
-+static int refresh_dir(struct dentry *root, unsigned int sigen)
-+{
-+	int err, i, j, ndentry, e;
-+	struct au_dcsub_pages dpages;
-+	struct au_dpage *dpage;
-+	struct dentry **dentries;
-+	struct inode *inode;
-+	const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
-+
-+	err = 0;
-+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
-+		if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
-+			ii_write_lock_child(inode);
-+			e = au_refresh_hinode_self(inode, /*do_attr*/1);
-+			ii_write_unlock(inode);
-+			if (unlikely(e)) {
-+				AuDbg("e %d, i%lu\n", e, inode->i_ino);
-+				if (!err)
-+					err = e;
-+				/* go on even if err */
-+			}
-+		}
-+
-+	e = au_dpages_init(&dpages, GFP_NOFS);
-+	if (unlikely(e)) {
-+		if (!err)
-+			err = e;
-+		goto out;
-+	}
-+	e = au_dcsub_pages(&dpages, root, test_dir, NULL);
-+	if (unlikely(e)) {
-+		if (!err)
-+			err = e;
-+		goto out_dpages;
-+	}
-+
-+	for (i = 0; !e && i < dpages.ndpage; i++) {
-+		dpage = dpages.dpages + i;
-+		dentries = dpage->dentries;
-+		ndentry = dpage->ndentry;
-+		for (j = 0; !e && j < ndentry; j++) {
-+			struct dentry *d;
-+
-+			d = dentries[j];
-+			au_dbg_verify_dir_parent(d, sigen);
-+			if (au_digen(d) != sigen) {
-+				e = do_refresh(d, S_IFDIR, flags);
-+				if (unlikely(e && !err))
-+					err = e;
-+				/* break on err */
-+			}
-+		}
-+	}
-+
-+ out_dpages:
-+	au_dpages_free(&dpages);
-+ out:
-+	return err;
-+}
-+
-+static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
-+{
-+	return !S_ISDIR(dentry->d_inode->i_mode);
-+}
-+
-+static int refresh_nondir(struct dentry *root, unsigned int sigen,
-+			  int do_dentry)
-+{
-+	int err, i, j, ndentry, e;
-+	struct au_dcsub_pages dpages;
-+	struct au_dpage *dpage;
-+	struct dentry **dentries;
-+	struct inode *inode;
-+
-+	err = 0;
-+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
-+		if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
-+			ii_write_lock_child(inode);
-+			e = au_refresh_hinode_self(inode, /*do_attr*/1);
-+			ii_write_unlock(inode);
-+			if (unlikely(e)) {
-+				AuDbg("e %d, i%lu\n", e, inode->i_ino);
-+				if (!err)
-+					err = e;
-+				/* go on even if err */
-+			}
-+		}
-+
-+	if (!do_dentry)
-+		goto out;
-+
-+	e = au_dpages_init(&dpages, GFP_NOFS);
-+	if (unlikely(e)) {
-+		if (!err)
-+			err = e;
-+		goto out;
-+	}
-+	e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
-+	if (unlikely(e)) {
-+		if (!err)
-+			err = e;
-+		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];
-+			au_dbg_verify_nondir_parent(d, sigen);
-+			inode = d->d_inode;
-+			if (inode && au_digen(d) != sigen) {
-+				e = do_refresh(d, inode->i_mode & S_IFMT,
-+					       /*dir_flags*/0);
-+				if (unlikely(e && !err))
-+					err = e;
-+				/* go on even err */
-+			}
-+		}
-+	}
-+
-+ out_dpages:
-+	au_dpages_free(&dpages);
-+ out:
-+	return err;
-+}
-+
-+static void au_remount_refresh(struct super_block *sb, unsigned int flags)
-+{
-+	int err;
-+	unsigned int sigen;
-+	struct au_sbinfo *sbinfo;
-+	struct dentry *root;
-+	struct inode *inode;
-+
-+	au_sigen_inc(sb);
-+	sigen = au_sigen(sb);
-+	sbinfo = au_sbi(sb);
-+	au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
-+
-+	root = sb->s_root;
-+	DiMustNoWaiters(root);
-+	inode = root->d_inode;
-+	IiMustNoWaiters(inode);
-+	au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
-+	di_write_unlock(root);
-+
-+	err = refresh_dir(root, sigen);
-+	if (unlikely(err)) {
-+		au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
-+		pr_warning("Refreshing directories failed, ignored (%d)\n",
-+			   err);
-+	}
-+
-+	if (au_ftest_opts(flags, REFRESH_NONDIR)) {
-+		err = refresh_nondir(root, sigen, !err);
-+		if (unlikely(err))
-+			pr_warning("Refreshing non-directories failed, ignored"
-+				   "(%d)\n", err);
-+	}
-+
-+	/* aufs_write_lock() calls ..._child() */
-+	di_write_lock_child(root);
-+	au_cpup_attr_all(root->d_inode, /*force*/1);
-+}
-+
-+/* 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;
-+	struct au_opts opts;
-+	struct dentry *root;
-+	struct inode *inode;
-+	struct au_sbinfo *sbinfo;
-+
-+	err = 0;
-+	root = sb->s_root;
-+	if (!data || !*data) {
-+		aufs_write_lock(root);
-+		err = au_opts_verify(sb, *flags, /*pending*/0);
-+		aufs_write_unlock(root);
-+		goto out;
-+	}
-+
-+	err = -ENOMEM;
-+	memset(&opts, 0, sizeof(opts));
-+	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 = root->d_inode;
-+	mutex_lock(&inode->i_mutex);
-+	aufs_write_lock(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_DIR)
-+	    || au_ftest_opts(opts.flags, REFRESH_NONDIR))
-+		au_remount_refresh(sb, opts.flags);
-+
-+	aufs_write_unlock(root);
-+	mutex_unlock(&inode->i_mutex);
-+
-+ out_opts:
-+	free_page((unsigned long)opts.opt);
-+ out:
-+	err = cvt_err(err);
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+static const struct super_operations aufs_sop = {
-+	.alloc_inode	= aufs_alloc_inode,
-+	.destroy_inode	= aufs_destroy_inode,
-+	.drop_inode	= generic_delete_inode,
-+	.show_options	= aufs_show_options,
-+	.statfs		= aufs_statfs,
-+	.put_super	= aufs_put_super,
-+	.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_dir_iop;
-+	inode->i_fop = &aufs_dir_fop;
-+	inode->i_mode = S_IFDIR;
-+	inode->i_nlink = 2;
-+	unlock_new_inode(inode);
-+
-+	root = d_alloc_root(inode);
-+	if (unlikely(!root))
-+		goto out_iput;
-+	err = PTR_ERR(root);
-+	if (IS_ERR(root))
-+		goto out_iput;
-+
-+	err = au_alloc_dinfo(root);
-+	if (!err) {
-+		sb->s_root = root;
-+		return 0; /* success */
-+	}
-+	dput(root);
-+	goto out; /* do not iput */
-+
-+ out_iput:
-+	iget_failed(inode);
-+	iput(inode);
-+ 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;
-+	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;
-+	memset(&opts, 0, sizeof(opts));
-+	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;
-+
-+	/* all timestamps always follow the ones on the branch */
-+	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
-+	sb->s_op = &aufs_sop;
-+	sb->s_magic = AUFS_SUPER_MAGIC;
-+	sb->s_maxbytes = 0;
-+	au_export_init(sb);
-+
-+	err = alloc_root(sb);
-+	if (unlikely(err)) {
-+		si_write_unlock(sb);
-+		goto out_info;
-+	}
-+	root = sb->s_root;
-+	inode = root->d_inode;
-+
-+	/*
-+	 * 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);
-+	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:
-+	kobject_put(&au_sbi(sb)->si_kobj);
-+	sb->s_fs_info = NULL;
-+ out_opts:
-+	free_page((unsigned long)opts.opt);
-+ out:
-+	AuTraceErr(err);
-+	err = cvt_err(err);
-+	AuTraceErr(err);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
-+		       const char *dev_name __maybe_unused, void *raw_data,
-+		       struct vfsmount *mnt)
-+{
-+	int err;
-+	struct super_block *sb;
-+
-+	/* all timestamps always follow the ones on the branch */
-+	/* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
-+	err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
-+	if (!err) {
-+		sb = mnt->mnt_sb;
-+		si_write_lock(sb);
-+		sysaufs_brs_add(sb, 0);
-+		si_write_unlock(sb);
-+	}
-+	return err;
-+}
-+
-+struct file_system_type aufs_fs_type = {
-+	.name		= AUFS_FSTYPE,
-+	.fs_flags	=
-+		FS_RENAME_DOES_D_MOVE	/* a race between rename and others */
-+		| FS_REVAL_DOT,		/* for NFS branch and udba */
-+	.get_sb		= aufs_get_sb,
-+	.kill_sb	= generic_shutdown_super,
-+	/* no need to __module_get() and module_put(). */
-+	.owner		= THIS_MODULE,
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/super.h linux-2.6.33.1/fs/aufs/super.h
---- linux-2.6.33.1-vanilla/fs/aufs/super.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/super.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,361 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * super_block operations
-+ */
-+
-+#ifndef __AUFS_SUPER_H__
-+#define __AUFS_SUPER_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+#include <linux/aufs_type.h>
-+#include "rwsem.h"
-+#include "spl.h"
-+#include "wkq.h"
-+
-+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
-+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
-+			       loff_t *);
-+
-+/* policies to select one among multiple writable branches */
-+struct au_wbr_copyup_operations {
-+	int (*copyup)(struct dentry *dentry);
-+};
-+
-+struct au_wbr_create_operations {
-+	int (*create)(struct dentry *dentry, int isdir);
-+	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;
-+};
-+
-+struct au_branch;
-+struct au_sbinfo {
-+	/* nowait tasks in the system-wide workqueue */
-+	struct au_nowait_tasks	si_nowait;
-+
-+	struct au_rwsem		si_rwsem;
-+
-+	/* branch management */
-+	unsigned int		si_generation;
-+
-+	/* see above flags */
-+	unsigned char		au_si_status;
-+
-+	aufs_bindex_t		si_bend;
-+	aufs_bindex_t		si_last_br_id;
-+	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;
-+
-+	/* mount flags */
-+	/* include/asm-ia64/siginfo.h defines a macro named si_flags */
-+	unsigned int		si_mntflags;
-+
-+	/* external inode number (bitmap and translation table) */
-+	au_readf_t		si_xread;
-+	au_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;
-+	/* 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
-+
-+	/* vdir parameters */
-+	unsigned long		si_rdcache;	/* max cache time in HZ */
-+	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;
-+
-+	/*
-+	 * rename(2) a directory with all children.
-+	 */
-+	/* reserved for future use */
-+	/* int			si_rendir; */
-+
-+	/* pseudo_link list */
-+	struct au_splhead	si_plink;
-+	wait_queue_head_t	si_plink_wq;
-+	spinlock_t		si_plink_maint_lock;
-+	struct file		*si_plink_maint;
-+
-+	/*
-+	 * 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, *si_dbgaufs_xib;
-+#ifdef CONFIG_AUFS_EXPORT
-+	struct dentry		 *si_dbgaufs_xigen;
-+#endif
-+#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_DIRS	1
-+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_DIR		(1 << 4)	/* target is a dir */
-+#define au_ftest_lock(flags, name)	((flags) & AuLock_##name)
-+#define au_fset_lock(flags, name)	{ (flags) |= AuLock_##name; }
-+#define au_fclr_lock(flags, name)	{ (flags) &= ~AuLock_##name; }
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* super.c */
-+extern struct file_system_type aufs_fs_type;
-+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
-+
-+/* 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);
-+
-+unsigned int au_sigen_inc(struct super_block *sb);
-+aufs_bindex_t au_new_br_id(struct super_block *sb);
-+
-+void 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);
-+void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
-+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);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
-+{
-+	return sb->s_fs_info;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+#ifdef CONFIG_AUFS_EXPORT
-+void au_export_init(struct super_block *sb);
-+
-+static inline int au_test_nfsd(struct task_struct *tsk)
-+{
-+	return !tsk->mm && !strcmp(tsk->comm, "nfsd");
-+}
-+
-+int 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(current))
-+		return -EBUSY;
-+	return -ESTALE;
-+}
-+#else
-+AuStubVoid(au_export_init, struct super_block *sb)
-+AuStubInt0(au_test_nfsd, struct task_struct *tsk)
-+AuStubInt0(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)
-+static inline int au_busy_or_stale(void)
-+{
-+	return -EBUSY;
-+}
-+#endif /* CONFIG_AUFS_EXPORT */
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
-+{
-+	/*
-+	 * This function is a dynamic '__init' fucntion 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_xib = NULL;
-+#ifdef CONFIG_AUFS_EXPORT
-+	sbinfo->si_dbgaufs_xigen = NULL;
-+#endif
-+#endif
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* lock superblock. mainly for entry point functions */
-+/*
-+ * si_noflush_read_lock, si_noflush_write_lock,
-+ * si_read_unlock, si_write_unlock, si_downgrade_lock
-+ */
-+AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
-+		       &au_sbi(sb)->si_rwsem);
-+AuSimpleUnlockRwsemFuncs(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_read_lock(struct super_block *sb, int flags)
-+{
-+	if (au_ftest_lock(flags, FLUSH))
-+		au_nwt_flush(&au_sbi(sb)->si_nowait);
-+	si_noflush_read_lock(sb);
-+}
-+
-+static inline void si_write_lock(struct super_block *sb)
-+{
-+	au_nwt_flush(&au_sbi(sb)->si_nowait);
-+	si_noflush_write_lock(sb);
-+}
-+
-+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);
-+}
-+
-+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);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline aufs_bindex_t au_sbend(struct super_block *sb)
-+{
-+	SiMustAnyLock(sb);
-+	return au_sbi(sb)->si_bend;
-+}
-+
-+static inline unsigned int au_mntflags(struct super_block *sb)
-+{
-+	SiMustAnyLock(sb);
-+	return au_sbi(sb)->si_mntflags;
-+}
-+
-+static inline unsigned int au_sigen(struct super_block *sb)
-+{
-+	SiMustAnyLock(sb);
-+	return au_sbi(sb)->si_generation;
-+}
-+
-+static inline struct au_branch *au_sbr(struct super_block *sb,
-+				       aufs_bindex_t bindex)
-+{
-+	SiMustAnyLock(sb);
-+	return au_sbi(sb)->si_branch[0 + bindex];
-+}
-+
-+static inline 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 -Nur linux-2.6.33.1-vanilla/fs/aufs/sysaufs.c linux-2.6.33.1/fs/aufs/sysaufs.c
---- linux-2.6.33.1-vanilla/fs/aufs/sysaufs.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/sysaufs.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,107 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sysfs interface and lifetime management
-+ * they are necessary regardless sysfs is disabled.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/random.h>
-+#include <linux/sysfs.h>
-+#include "aufs.h"
-+
-+unsigned long sysaufs_si_mask;
-+struct kset *sysaufs_ket;
-+
-+#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 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_ket;
-+	/* cf. sysaufs_name() */
-+	err = kobject_init_and_add
-+		(&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->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_ket->kobj, sysaufs_attr_group);
-+	kset_unregister(sysaufs_ket);
-+}
-+
-+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_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
-+	if (unlikely(!sysaufs_ket))
-+		goto out;
-+	err = PTR_ERR(sysaufs_ket);
-+	if (IS_ERR(sysaufs_ket))
-+		goto out;
-+	err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
-+	if (unlikely(err)) {
-+		kset_unregister(sysaufs_ket);
-+		goto out;
-+	}
-+
-+	err = dbgaufs_init();
-+	if (unlikely(err))
-+		sysaufs_fin();
-+ out:
-+	return err;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysaufs.h linux-2.6.33.1/fs/aufs/sysaufs.h
---- linux-2.6.33.1-vanilla/fs/aufs/sysaufs.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/sysaufs.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sysfs interface and mount lifetime management
-+ */
-+
-+#ifndef __SYSAUFS_H__
-+#define __SYSAUFS_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/sysfs.h>
-+#include <linux/aufs_type.h>
-+#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_ket;
-+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);
-+
-+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)
-+
-+static inline
-+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
-+			 char *buf)
-+{
-+	return 0;
-+}
-+
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/sysfs.c linux-2.6.33.1/fs/aufs/sysfs.c
---- linux-2.6.33.1-vanilla/fs/aufs/sysfs.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/sysfs.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,248 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sysfs interface
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include <linux/sysfs.h>
-+#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)
-+{
-+	struct path path;
-+	struct dentry *root;
-+	struct au_branch *br;
-+
-+	AuDbg("b%d\n", bindex);
-+
-+	root = sb->s_root;
-+	di_read_lock_parent(root, !AuLock_IR);
-+	br = au_sbr(sb, bindex);
-+	path.mnt = br->br_mnt;
-+	path.dentry = au_h_dptr(root, bindex);
-+	au_seq_path(seq, &path);
-+	di_read_unlock(root, !AuLock_IR);
-+	seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
-+	return 0;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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"
-+
-+/* todo: file size may exceed PAGE_SIZE */
-+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
-+			char *buf)
-+{
-+	ssize_t err;
-+	long l;
-+	aufs_bindex_t bend;
-+	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++;
-+	}
-+
-+	bend = au_sbend(sb);
-+	if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
-+		name += sizeof(SysaufsBr_PREFIX) - 1;
-+		err = strict_strtol(name, 10, &l);
-+		if (!err) {
-+			if (l <= bend)
-+				err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
-+			else
-+				err = -ENOENT;
-+		}
-+		goto out_seq;
-+	}
-+	BUG();
-+
-+ out_seq:
-+	if (!err) {
-+		err = seq->count;
-+		/* sysfs limit */
-+		if (unlikely(err == PAGE_SIZE))
-+			err = -EFBIG;
-+	}
-+	kfree(seq);
-+ out_unlock:
-+	si_read_unlock(sb);
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void sysaufs_br_init(struct au_branch *br)
-+{
-+	br->br_attr.name = br->br_name;
-+	br->br_attr.mode = S_IRUGO;
-+	br->br_attr.owner = THIS_MODULE;
-+}
-+
-+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+	struct au_branch *br;
-+	struct kobject *kobj;
-+	aufs_bindex_t bend;
-+
-+	dbgaufs_brs_del(sb, bindex);
-+
-+	if (!sysaufs_brs)
-+		return;
-+
-+	kobj = &au_sbi(sb)->si_kobj;
-+	bend = au_sbend(sb);
-+	for (; bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		sysfs_remove_file(kobj, &br->br_attr);
-+	}
-+}
-+
-+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
-+{
-+	int err;
-+	aufs_bindex_t bend;
-+	struct kobject *kobj;
-+	struct au_branch *br;
-+
-+	dbgaufs_brs_add(sb, bindex);
-+
-+	if (!sysaufs_brs)
-+		return;
-+
-+	kobj = &au_sbi(sb)->si_kobj;
-+	bend = au_sbend(sb);
-+	for (; bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
-+			 "%d", bindex);
-+		err = sysfs_create_file(kobj, &br->br_attr);
-+		if (unlikely(err))
-+			pr_warning("failed %s under sysfs(%d)\n",
-+				   br->br_name, err);
-+	}
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/sysrq.c linux-2.6.33.1/fs/aufs/sysrq.c
---- linux-2.6.33.1-vanilla/fs/aufs/sysrq.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/sysrq.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,119 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * magic sysrq hanlder
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+/* #include <linux/sysrq.h> */
-+#include "aufs.h"
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static void sysrq_sb(struct super_block *sb)
-+{
-+	char *plevel;
-+	struct au_sbinfo *sbinfo;
-+	struct file *file;
-+
-+	plevel = au_plevel;
-+	au_plevel = KERN_WARNING;
-+	au_debug(1);
-+
-+	sbinfo = au_sbi(sb);
-+	/* since we define pr_fmt, call printk directly */
-+	printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
-+	printk(KERN_WARNING AUFS_NAME ": superblock\n");
-+	au_dpri_sb(sb);
-+	printk(KERN_WARNING AUFS_NAME ": root dentry\n");
-+	au_dpri_dentry(sb->s_root);
-+	printk(KERN_WARNING AUFS_NAME ": root inode\n");
-+	au_dpri_inode(sb->s_root->d_inode);
-+#if 0
-+	struct inode *i;
-+	printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
-+	list_for_each_entry(i, &sb->s_inodes, i_sb_list)
-+		if (list_empty(&i->i_dentry))
-+			au_dpri_inode(i);
-+#endif
-+	printk(KERN_WARNING AUFS_NAME ": files\n");
-+	list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
-+		umode_t mode;
-+		mode = file->f_dentry->d_inode->i_mode;
-+		if (!special_file(mode) || au_special_file(mode))
-+			au_dpri_file(file);
-+	}
-+
-+	au_plevel = plevel;
-+	au_debug(0);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* 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 tty_struct *tty __maybe_unused)
-+{
-+	struct kobject *kobj;
-+	struct au_sbinfo *sbinfo;
-+
-+	/* spin_lock(&sysaufs_ket->list_lock); */
-+	list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
-+		sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
-+		sysrq_sb(sbinfo->si_sb);
-+	}
-+	/* spin_unlock(&sysaufs_ket->list_lock); */
-+}
-+
-+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 -Nur linux-2.6.33.1-vanilla/fs/aufs/vdir.c linux-2.6.33.1/fs/aufs/vdir.c
---- linux-2.6.33.1-vanilla/fs/aufs/vdir.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/vdir.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,884 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * virtual or vertical directory
-+ */
-+
-+#include <linux/hash.h>
-+#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 apropriate 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;
-+
-+	head = kmalloc(sizeof(*nhash->nh_head) * num_hash, 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 *tpos;
-+	struct hlist_node *pos, *node;
-+
-+	hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
-+		/* hlist_del(pos); */
-+		kfree(tpos);
-+	}
-+}
-+
-+static void au_nhash_de_do_free(struct hlist_head *head)
-+{
-+	struct au_vdir_dehstr *tpos;
-+	struct hlist_node *pos, *node;
-+
-+	hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
-+		/* hlist_del(pos); */
-+		au_cache_free_vdir_dehstr(tpos);
-+	}
-+}
-+
-+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++);
-+	}
-+	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 *tpos;
-+	struct hlist_node *pos;
-+
-+	num = 0;
-+	n = whlist->nh_num;
-+	head = whlist->nh_head;
-+	for (u = 0; u < n; u++, head++)
-+		hlist_for_each_entry(tpos, pos, head, wh_hash)
-+			if (tpos->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;
-+	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 *tpos;
-+	struct hlist_node *pos;
-+	struct au_vdir_destr *str;
-+
-+	head = au_name_hash(whlist, name, nlen);
-+	hlist_for_each_entry(tpos, pos, head, wh_hash) {
-+		str = &tpos->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 *tpos;
-+	struct hlist_node *pos;
-+	struct au_vdir_destr *str;
-+
-+	head = au_name_hash(delist, name, nlen);
-+	hlist_for_each_entry(tpos, pos, head, hash) {
-+		str = tpos->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 = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
-+		     GFP_NOFS);
-+	if (unlikely(!o))
-+		goto out;
-+
-+	vdir->vd_deblk = o;
-+	p.deblk = kmalloc(deblk_sz, GFP_NOFS);
-+	if (p.deblk) {
-+		ul = vdir->vd_nblk++;
-+		vdir->vd_deblk[ul] = p.deblk;
-+		vdir->vd_last.ul = ul;
-+		vdir->vd_last.p.deblk = p.deblk;
-+		deblk_end.deblk = p.deblk + deblk_sz;
-+		err = set_deblk_end(&p, &deblk_end);
-+	}
-+
-+ out:
-+	return err;
-+}
-+
-+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
-+		     unsigned int d_type, struct au_nhash *delist)
-+{
-+	int err;
-+	unsigned int sz;
-+	const unsigned int deblk_sz = vdir->vd_deblk_sz;
-+	union au_vdir_deblk_p p, *room, deblk_end;
-+	struct au_vdir_dehstr *dehstr;
-+
-+	p.deblk = last_deblk(vdir);
-+	deblk_end.deblk = p.deblk + deblk_sz;
-+	room = &vdir->vd_last.p;
-+	AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
-+		  || !is_deblk_end(room, &deblk_end));
-+
-+	sz = calc_size(nlen);
-+	if (unlikely(sz > deblk_end.deblk - room->deblk)) {
-+		err = append_deblk(vdir);
-+		if (unlikely(err))
-+			goto out;
-+
-+		p.deblk = last_deblk(vdir);
-+		deblk_end.deblk = p.deblk + deblk_sz;
-+		/* smp_mb(); */
-+		AuDebugOn(room->deblk != p.deblk);
-+	}
-+
-+	err = -ENOMEM;
-+	dehstr = au_cache_alloc_vdir_dehstr();
-+	if (unlikely(!dehstr))
-+		goto out;
-+
-+	dehstr->str = &room->de->de_str;
-+	hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
-+	room->de->de_ino = ino;
-+	room->de->de_type = d_type;
-+	room->de->de_str.len = nlen;
-+	memcpy(room->de->de_str.name, name, nlen);
-+
-+	err = 0;
-+	room->deblk += sz;
-+	if (unlikely(set_deblk_end(room, &deblk_end)))
-+		err = append_deblk(vdir);
-+	/* smp_mb(); */
-+
-+ out:
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+void au_vdir_free(struct au_vdir *vdir)
-+{
-+	unsigned char **deblk;
-+
-+	deblk = vdir->vd_deblk;
-+	while (vdir->vd_nblk--)
-+		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_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 apropriate 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 */
-+
-+	kfree(vdir->vd_deblk);
-+
-+ out_free:
-+	au_cache_free_vdir(vdir);
-+ out:
-+	vdir = ERR_PTR(err);
-+	return vdir;
-+}
-+
-+static int reinit_vdir(struct au_vdir *vdir)
-+{
-+	int err;
-+	union au_vdir_deblk_p p, deblk_end;
-+
-+	while (vdir->vd_nblk > 1) {
-+		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)	{ (flags) |= AuFillVdir_##name; }
-+#define au_fclr_fillvdir(flags, name)	{ (flags) &= ~AuFillVdir_##name; }
-+
-+#ifndef CONFIG_AUFS_SHWH
-+#undef AuFillVdir_SHWH
-+#define AuFillVdir_SHWH		0
-+#endif
-+
-+struct fillvdir_arg {
-+	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(void *__arg, const char *__name, int nlen,
-+		    loff_t offset __maybe_unused, u64 h_ino,
-+		    unsigned int d_type)
-+{
-+	struct fillvdir_arg *arg = __arg;
-+	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_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 */
-+
-+		sb = arg->file->f_dentry->d_sb;
-+		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 *tpos;
-+	struct hlist_node *pos, *n;
-+	char *p, *o;
-+	struct au_vdir_destr *destr;
-+
-+	AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
-+
-+	err = -ENOMEM;
-+	o = p = __getname_gfp(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(tpos, pos, n, head, wh_hash) {
-+			destr = &tpos->wh_str;
-+			memcpy(p, destr->name, destr->len);
-+			err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
-+					tpos->wh_ino, tpos->wh_type, delist);
-+			if (unlikely(err))
-+				break;
-+		}
-+	}
-+
-+	__putname(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 bend, bindex, bstart;
-+	unsigned char shwh;
-+	struct file *hf, *file;
-+	struct super_block *sb;
-+
-+	file = arg->file;
-+	sb = file->f_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);
-+	}
-+	bstart = au_fbstart(file);
-+	bend = au_fbend(file);
-+	for (bindex = bstart; !err && bindex <= bend; bindex++) {
-+		hf = au_h_fptr(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 != bend
-+			&& 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_readdir(hf, fillvdir, arg);
-+			if (err >= 0)
-+				err = arg->err;
-+		} while (!err && au_ftest_fillvdir(arg->flags, CALLED));
-+	}
-+
-+	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;
-+	struct inode *inode;
-+	struct au_vdir *vdir, *allocated;
-+
-+	err = 0;
-+	inode = file->f_dentry->d_inode;
-+	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; */
-+		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);
-+
-+ 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 = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
-+			     GFP_NOFS);
-+		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 = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
-+		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;
-+
-+	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) {
-+		err = reinit_vdir(vdir_cache);
-+		if (unlikely(err))
-+			goto out;
-+	} else
-+		return 0; /* success */
-+
-+	inode = file->f_dentry->d_inode;
-+	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);
-+
-+ 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)
-+{
-+	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 (file->f_pos == offset)
-+		goto out;
-+
-+	vdir_cache->vd_last.ul = 0;
-+	vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
-+	if (!file->f_pos)
-+		goto out;
-+
-+	valid = 0;
-+	deblk_sz = vdir_cache->vd_deblk_sz;
-+	ul = div64_u64(file->f_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 < file->f_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, void *dirent, filldir_t filldir)
-+{
-+	int err;
-+	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))
-+		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, file->f_pos,
-+			      (unsigned long)de->de_ino, de->de_type);
-+			err = filldir(dirent, de->de_str.name, de->de_str.len,
-+				      file->f_pos, de->de_ino, de->de_type);
-+			if (unlikely(err)) {
-+				AuTraceErr(err);
-+				/* 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;
-+			file->f_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];
-+			file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
-+			continue;
-+		}
-+		break;
-+	}
-+
-+	/* smp_mb(); */
-+	return 0;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/vfsub.c linux-2.6.33.1/fs/aufs/vfsub.c
---- linux-2.6.33.1-vanilla/fs/aufs/vfsub.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/vfsub.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,790 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sub-routines for VFS
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/ima.h>
-+#include <linux/namei.h>
-+#include <linux/security.h>
-+#include <linux/splice.h>
-+#include <linux/uaccess.h>
-+#include "aufs.h"
-+
-+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->mnt, h_path->dentry, &st);
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_conv_oflags(int flags)
-+{
-+	int mask = 0;
-+
-+#ifdef CONFIG_IMA
-+	fmode_t fmode;
-+
-+	/* mask = MAY_OPEN; */
-+	fmode = OPEN_FMODE(flags);
-+	if (fmode & FMODE_READ)
-+		mask |= MAY_READ;
-+	if ((fmode & FMODE_WRITE)
-+	    || (flags & O_TRUNC))
-+		mask |= MAY_WRITE;
-+	/*
-+	 * if (flags & O_APPEND)
-+	 *	mask |= MAY_APPEND;
-+	 */
-+	if (flags & vfsub_fmode_to_uint(FMODE_EXEC))
-+		mask |= MAY_EXEC;
-+
-+	AuDbg("flags 0x%x, mask 0x%x\n", flags, mask);
-+#endif
-+
-+	return mask;
-+}
-+
-+struct file *vfsub_dentry_open(struct path *path, int flags)
-+{
-+	struct file *file;
-+	int err;
-+
-+	path_get(path);
-+	file = dentry_open(path->dentry, path->mnt, flags, current_cred());
-+	if (IS_ERR(file))
-+		goto out;
-+
-+	err = ima_file_check(file, au_conv_oflags(flags));
-+	if (unlikely(err)) {
-+		fput(file);
-+		file = ERR_PTR(err);
-+	}
-+out:
-+	return file;
-+}
-+
-+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
-+{
-+	struct file *file;
-+
-+	/* lockdep_off(); */
-+	file = filp_open(path, oflags, mode);
-+	/* lockdep_on(); */
-+	if (IS_ERR(file))
-+		goto out;
-+	vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
-+
-+ out:
-+	return file;
-+}
-+
-+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
-+{
-+	int err;
-+
-+	/* lockdep_off(); */
-+	err = kern_path(name, flags, path);
-+	/* lockdep_on(); */
-+	if (!err && path->dentry->d_inode)
-+		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(parent->d_inode);
-+
-+	path.dentry = lookup_one_len(name, parent, len);
-+	if (IS_ERR(path.dentry))
-+		goto out;
-+	if (path.dentry->d_inode)
-+		vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
-+
-+ out:
-+	AuTraceErrPtr(path.dentry);
-+	return path.dentry;
-+}
-+
-+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
-+{
-+	struct path path = {
-+		.mnt = nd->path.mnt
-+	};
-+
-+	IMustLock(nd->path.dentry->d_inode);
-+
-+	path.dentry = lookup_hash(nd);
-+	if (IS_ERR(path.dentry))
-+		goto out;
-+	if (path.dentry->d_inode)
-+		vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
-+
-+ out:
-+	AuTraceErrPtr(path.dentry);
-+	return path.dentry;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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)
-+{
-+	int err;
-+	struct dentry *d;
-+
-+	IMustLock(dir);
-+
-+	d = path->dentry;
-+	path->dentry = d->d_parent;
-+	err = security_path_mknod(path, path->dentry, mode, 0);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	if (au_test_fs_null_nd(dir->i_sb))
-+		err = vfs_create(dir, path->dentry, mode, NULL);
-+	else {
-+		struct nameidata h_nd;
-+
-+		memset(&h_nd, 0, sizeof(h_nd));
-+		h_nd.flags = LOOKUP_CREATE;
-+		h_nd.intent.open.flags = O_CREAT
-+			| vfsub_fmode_to_uint(FMODE_READ);
-+		h_nd.intent.open.create_mode = mode;
-+		h_nd.path.dentry = path->dentry->d_parent;
-+		h_nd.path.mnt = path->mnt;
-+		path_get(&h_nd.path);
-+		err = vfs_create(dir, path->dentry, mode, &h_nd);
-+		path_put(&h_nd.path);
-+	}
-+
-+	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, path->dentry, symname);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = vfs_symlink(dir, path->dentry, symname);
-+	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, path->dentry, mode, dev);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = vfs_mknod(dir, path->dentry, mode, dev);
-+	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)
-+{
-+	int err;
-+	struct dentry *d;
-+
-+	IMustLock(dir);
-+
-+	err = au_test_nlink(src_dentry->d_inode);
-+	if (unlikely(err))
-+		return err;
-+
-+	d = path->dentry;
-+	path->dentry = d->d_parent;
-+	err = security_path_link(src_dentry, path, path->dentry);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	/* lockdep_off(); */
-+	err = vfs_link(src_dentry, dir, path->dentry);
-+	/* 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)
-+{
-+	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, path->dentry);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	/* lockdep_off(); */
-+	err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
-+	/* 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, path->dentry, mode);
-+	path->dentry = d;
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = vfs_mkdir(dir, path->dentry, mode);
-+	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, path->dentry);
-+	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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
-+		     loff_t *ppos)
-+{
-+	ssize_t err;
-+
-+	err = vfs_read(file, ubuf, count, ppos);
-+	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;
-+
-+	oldfs = get_fs();
-+	set_fs(KERNEL_DS);
-+	err = vfsub_read_u(file, (char __user *)kbuf, 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;
-+
-+	oldfs = get_fs();
-+	set_fs(KERNEL_DS);
-+	err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
-+	set_fs(oldfs);
-+	return err;
-+}
-+
-+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
-+{
-+	int err;
-+
-+	/* lockdep_off(); */
-+	err = vfs_readdir(file, filldir, arg);
-+	/* 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(); */
-+	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;
-+}
-+
-+/* 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;
-+
-+	h_inode = h_path->dentry->d_inode;
-+	if (!h_file) {
-+		err = mnt_want_write(h_path->mnt);
-+		if (err)
-+			goto out;
-+		err = inode_permission(h_inode, MAY_WRITE);
-+		if (err)
-+			goto out_mnt;
-+		err = get_write_access(h_inode);
-+		if (err)
-+			goto out_mnt;
-+		err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
-+		if (err)
-+			goto out_inode;
-+	}
-+
-+	err = locks_verify_truncate(h_inode, h_file, length);
-+	if (!err)
-+		err = security_path_truncate(h_path, length, attr);
-+	if (!err) {
-+		/* lockdep_off(); */
-+		err = do_truncate(h_path->dentry, length, attr, h_file);
-+		/* lockdep_on(); */
-+	}
-+
-+ out_inode:
-+	if (!h_file)
-+		put_write_access(h_inode);
-+ out_mnt:
-+	if (!h_file)
-+		mnt_drop_write(h_path->mnt);
-+ 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)
-+		err = vfsub_mkdir(dir, path, mode);
-+	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)
-+		err = vfsub_rmdir(dir, path);
-+	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;
-+};
-+
-+static void call_notify_change(void *args)
-+{
-+	struct notify_change_args *a = args;
-+	struct inode *h_inode;
-+
-+	h_inode = a->path->dentry->d_inode;
-+	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);
-+		/* 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)
-+{
-+	int err;
-+	struct notify_change_args args = {
-+		.errp	= &err,
-+		.path	= path,
-+		.ia	= ia
-+	};
-+
-+	call_notify_change(&args);
-+
-+	return err;
-+}
-+
-+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
-+{
-+	int err, wkq_err;
-+	struct notify_change_args args = {
-+		.errp	= &err,
-+		.path	= path,
-+		.ia	= ia
-+	};
-+
-+	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;
-+};
-+
-+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)
-+				      && atomic_read(&d->d_count) == 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 = d->d_inode;
-+	if (h_inode)
-+		atomic_inc(&h_inode->i_count);
-+
-+	/* lockdep_off(); */
-+	*a->errp = vfs_unlink(a->dir, d);
-+	/* 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, int force)
-+{
-+	int err;
-+	struct unlink_args args = {
-+		.errp	= &err,
-+		.dir	= dir,
-+		.path	= path
-+	};
-+
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/vfsub.h linux-2.6.33.1/fs/aufs/vfsub.h
---- linux-2.6.33.1-vanilla/fs/aufs/vfsub.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/vfsub.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,175 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * sub-routines for VFS
-+ */
-+
-+#ifndef __AUFS_VFSUB_H__
-+#define __AUFS_VFSUB_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* lock subclass for lower inode */
-+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
-+/* reduce? gave up. */
-+enum {
-+	AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
-+	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)
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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);
-+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 dentry *vfsub_lookup_hash(struct nameidata *nd);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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);
-+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);
-+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
-+		 struct inode *hdir, struct path *path);
-+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_readdir(struct file *file, filldir_t filldir, void *arg);
-+
-+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 void vfsub_file_accessed(struct file *h_file)
-+{
-+	file_accessed(h_file);
-+	vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
-+}
-+
-+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_mnt, h_dentry);
-+	vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
-+}
-+
-+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);
-+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
-+		struct file *h_file);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* dirty workaround for strict type of fmode_t */
-+union vfsub_fmu {
-+	fmode_t fm;
-+	unsigned int ui;
-+};
-+
-+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
-+{
-+	union vfsub_fmu u = {
-+		.fm = fm
-+	};
-+
-+	BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
-+
-+	return u.ui;
-+}
-+
-+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
-+{
-+	union vfsub_fmu u = {
-+		.ui = ui
-+	};
-+
-+	return u.fm;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+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);
-+int vfsub_notify_change(struct path *path, struct iattr *ia);
-+int vfsub_unlink(struct inode *dir, struct path *path, int force);
-+
-+#endif /* __KERNEL__ */
-+#endif /* __AUFS_VFSUB_H__ */
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/wbr_policy.c \
                linux-2.6.33.1/fs/aufs/wbr_policy.c
---- linux-2.6.33.1-vanilla/fs/aufs/wbr_policy.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/wbr_policy.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,637 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * policies for selecting one among multiple writable branches
-+ */
-+
-+#include <linux/statfs.h>
-+#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 = h_src->d_inode;
-+	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(h_path->dentry->d_inode, h_isrc);
-+	err = vfsub_sio_notify_change(h_path, &ia);
-+
-+	/* 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);
-+	}
-+
-+	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)	{ (flags) |= AuCpdown_##name; }
-+#define au_fclr_cpdown(flags, name)	{ (flags) &= ~AuCpdown_##name; }
-+
-+struct au_cpdown_dir_args {
-+	struct dentry *parent;
-+	unsigned int flags;
-+};
-+
-+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
-+			     struct au_cpdown_dir_args *a)
-+{
-+	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(a->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 (h_path.dentry->d_inode) {
-+		h_path.mnt = br->br_mnt;
-+		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 dentry *h_parent, void *arg)
-+{
-+	int err, rerr;
-+	aufs_bindex_t bopq, bstart;
-+	struct path h_path;
-+	struct dentry *parent;
-+	struct inode *h_dir, *h_inode, *inode, *dir;
-+	struct au_cpdown_dir_args *args = arg;
-+
-+	bstart = au_dbstart(dentry);
-+	/* dentry is di-locked */
-+	parent = dget_parent(dentry);
-+	dir = parent->d_inode;
-+	h_dir = h_parent->d_inode;
-+	AuDebugOn(h_dir != au_h_iptr(dir, bdst));
-+	IMustLock(h_dir);
-+
-+	err = au_lkup_neg(dentry, bdst);
-+	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(args->flags, MADE_DIR);
-+
-+	bopq = au_dbdiropq(dentry);
-+	au_fclr_cpdown(args->flags, WHED);
-+	au_fclr_cpdown(args->flags, DIROPQ);
-+	if (au_dbwh(dentry) == bdst)
-+		au_fset_cpdown(args->flags, WHED);
-+	if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
-+		au_fset_cpdown(args->flags, PARENT_OPQ);
-+	h_inode = h_path.dentry->d_inode;
-+	mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
-+	if (au_ftest_cpdown(args->flags, WHED)) {
-+		err = au_cpdown_dir_opq(dentry, bdst, args);
-+		if (unlikely(err)) {
-+			mutex_unlock(&h_inode->i_mutex);
-+			goto out_dir;
-+		}
-+	}
-+
-+	err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
-+	mutex_unlock(&h_inode->i_mutex);
-+	if (unlikely(err))
-+		goto out_opq;
-+
-+	if (au_ftest_cpdown(args->flags, WHED)) {
-+		err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
-+		if (unlikely(err))
-+			goto out_opq;
-+	}
-+
-+	inode = dentry->d_inode;
-+	if (au_ibend(inode) < bdst)
-+		au_set_ibend(inode, bdst);
-+	au_set_h_iptr(inode, bdst, au_igrab(h_inode),
-+		      au_hi_flags(inode, /*isdir*/1));
-+	goto out; /* success */
-+
-+	/* revert */
-+ out_opq:
-+	if (au_ftest_cpdown(args->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 %.*s b%d (%d)\n",
-+				AuDLNPair(dentry), bdst, rerr);
-+			err = -EIO;
-+			goto out;
-+		}
-+	}
-+ out_dir:
-+	if (au_ftest_cpdown(args->flags, MADE_DIR)) {
-+		rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
-+		if (unlikely(rerr)) {
-+			AuIOErr("failed removing %.*s b%d (%d)\n",
-+				AuDLNPair(dentry), bdst, rerr);
-+			err = -EIO;
-+		}
-+	}
-+ out_put:
-+	au_set_h_dptr(dentry, bdst, NULL);
-+	if (au_dbend(dentry) == bdst)
-+		au_update_dbend(dentry);
-+ out:
-+	dput(parent);
-+	return err;
-+}
-+
-+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
-+{
-+	int err;
-+	struct au_cpdown_dir_args args = {
-+		.parent	= dget_parent(dentry),
-+		.flags	= 0
-+	};
-+
-+	err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
-+	dput(args.parent);
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* policies for create */
-+
-+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, int isdir __maybe_unused)
-+{
-+	int err;
-+	aufs_bindex_t bstart, bindex;
-+	struct super_block *sb;
-+	struct dentry *parent, *h_parent;
-+
-+	sb = dentry->d_sb;
-+	bstart = au_dbstart(dentry);
-+	err = bstart;
-+	if (!au_br_rdonly(au_sbr(sb, bstart)))
-+		goto out;
-+
-+	err = -EROFS;
-+	parent = dget_parent(dentry);
-+	for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
-+		h_parent = au_h_dptr(parent, bindex);
-+		if (!h_parent || !h_parent->d_inode)
-+			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, bstart - 1);
-+
-+ 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 && 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_sbend(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, int isdir)
-+{
-+	int err, nbr;
-+	unsigned int u;
-+	aufs_bindex_t bindex, bend;
-+	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;
-+	bend = au_sbend(sb);
-+	nbr = bend + 1;
-+	for (bindex = 0; bindex <= bend; bindex++) {
-+		if (!isdir) {
-+			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;
-+	}
-+
-+ out:
-+	AuDbg("%d\n", err);
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* most free space */
-+static void au_mfs(struct dentry *dentry)
-+{
-+	struct super_block *sb;
-+	struct au_branch *br;
-+	struct au_wbr_mfs *mfs;
-+	aufs_bindex_t bindex, bend;
-+	int err;
-+	unsigned long long b, bavail;
-+	/* 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;
-+	bend = au_sbend(sb);
-+	for (bindex = 0; bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		if (au_br_rdonly(br))
-+			continue;
-+
-+		/* sb->s_root for NFS is unreliable */
-+		err = vfs_statfs(br->br_mnt->mnt_root, 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);
-+	kfree(st);
-+}
-+
-+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
-+{
-+	int err;
-+	struct super_block *sb;
-+	struct au_wbr_mfs *mfs;
-+
-+	err = au_wbr_create_exp(dentry);
-+	if (err >= 0)
-+		goto out;
-+
-+	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_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
-+		au_mfs(dentry);
-+	mutex_unlock(&mfs->mfs_lock);
-+	err = mfs->mfs_bindex;
-+
-+ 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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* most free space and then round robin */
-+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
-+{
-+	int err;
-+	struct au_wbr_mfs *mfs;
-+
-+	err = au_wbr_create_mfs(dentry, isdir);
-+	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, isdir);
-+		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, int isdir)
-+{
-+	int err, e2;
-+	unsigned long long b;
-+	aufs_bindex_t bindex, bstart, bend;
-+	struct super_block *sb;
-+	struct dentry *parent, *h_parent;
-+	struct au_branch *br;
-+
-+	err = au_wbr_create_tdp(dentry, isdir);
-+	if (unlikely(err < 0))
-+		goto out;
-+	parent = dget_parent(dentry);
-+	bstart = au_dbstart(parent);
-+	bend = au_dbtaildir(parent);
-+	if (bstart == bend)
-+		goto out_parent; /* success */
-+
-+	e2 = au_wbr_create_mfs(dentry, isdir);
-+	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 = bstart; bindex <= bend; bindex++) {
-+		h_parent = au_h_dptr(parent, bindex);
-+		if (!h_parent || !h_parent->d_inode)
-+			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);
-+		}
-+	}
-+
-+ out_parent:
-+	dput(parent);
-+ 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, /*isdir, anything is ok*/0);
-+}
-+
-+/* bottom up parent */
-+static int au_wbr_copyup_bup(struct dentry *dentry)
-+{
-+	int err;
-+	aufs_bindex_t bindex, bstart;
-+	struct dentry *parent, *h_parent;
-+	struct super_block *sb;
-+
-+	err = -EROFS;
-+	sb = dentry->d_sb;
-+	parent = dget_parent(dentry);
-+	bstart = au_dbstart(parent);
-+	for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
-+		h_parent = au_h_dptr(parent, bindex);
-+		if (!h_parent || !h_parent->d_inode)
-+			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, bstart - 1);
-+
-+	AuDbg("b%d\n", err);
-+	return err;
-+}
-+
-+/* bottom up */
-+static int au_wbr_copyup_bu(struct dentry *dentry)
-+{
-+	int err;
-+
-+	err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
-+
-+	AuDbg("b%d\n", err);
-+	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_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
-+	}
-+};
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/whout.c linux-2.6.33.1/fs/aufs/whout.c
---- linux-2.6.33.1-vanilla/fs/aufs/whout.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/whout.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,1052 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * whiteout for logical deletion and opaque directory
-+ */
-+
-+#include <linux/fs.h>
-+#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 = {
-+	.name = AUFS_WH_DIROPQ,
-+	.len = 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,
-+	       struct au_branch *br, int try_sio)
-+{
-+	int err;
-+	struct dentry *wh_dentry;
-+
-+	if (!try_sio)
-+		wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
-+	else
-+		wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
-+	err = PTR_ERR(wh_dentry);
-+	if (IS_ERR(wh_dentry))
-+		goto out;
-+
-+	err = 0;
-+	if (!wh_dentry->d_inode)
-+		goto out_wh; /* success */
-+
-+	err = 1;
-+	if (S_ISREG(wh_dentry->d_inode->i_mode))
-+		goto out_wh; /* success */
-+
-+	err = -EIO;
-+	AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
-+		AuDLNPair(wh_dentry), wh_dentry->d_inode->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, struct au_branch *br)
-+{
-+	int err;
-+	struct inode *h_dir;
-+
-+	h_dir = h_dentry->d_inode;
-+	err = au_wh_test(h_dentry, &diropq_name, br,
-+			 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_MIN + 1],
-+		*name, *p;
-+	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_MIN + prefix->len - 1;
-+	if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
-+		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, "%.*d", AUFS_WH_TMP_LEN, cnt++);
-+		dentry = au_sio_lkup_one(&qs, h_parent, br);
-+		if (IS_ERR(dentry) || !dentry->d_inode)
-+			goto out_name;
-+		dput(dentry);
-+	}
-+	/* pr_warning("could not get random name\n"); */
-+	dentry = ERR_PTR(-EEXIST);
-+	AuDbg("%.*s\n", AuLNPair(&qs));
-+	BUG();
-+
-+ out_name:
-+	if (name != defname)
-+		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 = br->br_mnt
-+	};
-+	struct inode *h_dir;
-+	struct dentry *h_parent;
-+
-+	h_parent = h_dentry->d_parent; /* dir inode is locked */
-+	h_dir = h_parent->d_inode;
-+	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() */
-+	err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
-+	AuTraceErr(err);
-+	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 force;
-+
-+	/*
-+	 * 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)
-+		&& h_path->dentry->d_inode->i_uid != current_fsuid();
-+	return vfsub_unlink(h_dir, h_path, force);
-+}
-+
-+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 = br->br_mnt
-+	};
-+
-+	err = 0;
-+	h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
-+	if (IS_ERR(h_path.dentry))
-+		err = PTR_ERR(h_path.dentry);
-+	else {
-+		if (h_path.dentry->d_inode
-+		    && S_ISREG(h_path.dentry->d_inode->i_mode))
-+			err = do_unlink_wh(h_parent->d_inode, &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;
-+
-+	if (!whpath->dentry->d_inode)
-+		return;
-+
-+	err = mnt_want_write(whpath->mnt);
-+	if (!err) {
-+		if (isdir)
-+			err = vfsub_rmdir(h_dir, whpath);
-+		else
-+			err = vfsub_unlink(h_dir, whpath, /*force*/0);
-+		mnt_drop_write(whpath->mnt);
-+	}
-+	if (unlikely(err))
-+		pr_warning("failed removing %.*s (%d), ignored.\n",
-+			   AuDLNPair(whpath->dentry), err);
-+}
-+
-+static int test_linkable(struct dentry *h_root)
-+{
-+	struct inode *h_dir = h_root->d_inode;
-+
-+	if (h_dir->i_op->link)
-+		return 0;
-+
-+	pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
-+	       AuDLNPair(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 (!path->dentry->d_inode) {
-+		int mode = S_IRWXU;
-+
-+		if (au_test_nfs(path->dentry->d_sb))
-+			mode |= S_IXUGO;
-+		err = mnt_want_write(path->mnt);
-+		if (!err) {
-+			err = vfsub_mkdir(h_dir, path, mode);
-+			mnt_drop_write(path->mnt);
-+		}
-+	} else if (S_ISDIR(path->dentry->d_inode->i_mode))
-+		err = 0;
-+	else
-+		pr_err("unknown %.*s exists\n", AuDLNPair(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 mesage
-+ * zero: succuess
-+ * plus: error, caller should NOT print the mesage
-+ */
-+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 = h_root->d_inode;
-+	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 = h_root->d_inode;
-+	if (!base[AuBrWh_BASE].dentry->d_inode) {
-+		err = mnt_want_write(h_path->mnt);
-+		if (!err) {
-+			h_path->dentry = base[AuBrWh_BASE].dentry;
-+			err = vfsub_create(h_dir, h_path, WH_MASK);
-+			mnt_drop_write(h_path->mnt);
-+		}
-+	} else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
-+		err = 0;
-+	else
-+		pr_err("unknown %.*s/%.*s exists\n",
-+		       AuDLNPair(h_root), AuDLNPair(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 dentry *h_root, struct au_branch *br,
-+	       struct super_block *sb)
-+{
-+	int err, i;
-+	const unsigned char do_plink
-+		= !!au_opt_test(au_mntflags(sb), PLINK);
-+	struct path path = {
-+		.mnt = br->br_mnt
-+	};
-+	struct inode *h_dir;
-+	struct au_wbr *wbr = br->br_wbr;
-+	static const struct qstr base_name[] = {
-+		[AuBrWh_BASE] = {
-+			.name	= AUFS_BASE_NAME,
-+			.len	= sizeof(AUFS_BASE_NAME) - 1
-+		},
-+		[AuBrWh_PLINK] = {
-+			.name	= AUFS_PLINKDIR_NAME,
-+			.len	= sizeof(AUFS_PLINKDIR_NAME) - 1
-+		},
-+		[AuBrWh_ORPH] = {
-+			.name	= AUFS_ORPHDIR_NAME,
-+			.len	= 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;
-+	switch (br->br_perm) {
-+	case AuBrPerm_RO:
-+	case AuBrPerm_ROWH:
-+	case AuBrPerm_RR:
-+	case AuBrPerm_RRWH:
-+		h_dir = h_root->d_inode;
-+		au_wh_init_ro(h_dir, base, &path);
-+		break;
-+
-+	case AuBrPerm_RWNoLinkWH:
-+		err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
-+		if (err > 0)
-+			goto out;
-+		else if (err)
-+			goto out_err;
-+		break;
-+
-+	case AuBrPerm_RW:
-+		err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
-+		if (err > 0)
-+			goto out;
-+		else if (err)
-+			goto out_err;
-+		break;
-+
-+	default:
-+		BUG();
-+	}
-+	goto out; /* success */
-+
-+ out_err:
-+	pr_err("an error(%d) on the writable branch %.*s(%s)\n",
-+	       err, AuDLNPair(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;
-+	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 = a->sb->s_root->d_inode;
-+	hdir = au_hi(dir, bindex);
-+	h_root = au_h_dptr(a->sb->s_root, bindex);
-+
-+	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) {
-+		err = mnt_want_write(a->br->br_mnt);
-+		if (!err) {
-+			h_path.dentry = wbr->wbr_whbase;
-+			h_path.mnt = a->br->br_mnt;
-+			err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
-+			mnt_drop_write(a->br->br_mnt);
-+		}
-+	} else {
-+		pr_warning("%.*s is moved, ignored\n",
-+			   AuDLNPair(wbr->wbr_whbase));
-+		err = 0;
-+	}
-+	dput(wbr->wbr_whbase);
-+	wbr->wbr_whbase = NULL;
-+	if (!err)
-+		err = au_wh_init(h_root, a->br, a->sb);
-+	wbr_wh_write_unlock(wbr);
-+	au_hn_imtx_unlock(hdir);
-+	di_read_unlock(a->sb->s_root, AuLock_IR);
-+
-+ out:
-+	if (wbr)
-+		atomic_dec(&wbr->wbr_wh_running);
-+	atomic_dec(&a->br->br_count);
-+	au_nwt_done(&au_sbi(a->sb)->si_nowait);
-+	si_write_unlock(a->sb);
-+	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;
-+		atomic_inc(&br->br_count);
-+		wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
-+		if (unlikely(wkq_err)) {
-+			atomic_dec(&br->br_wbr->wbr_wh_running);
-+			atomic_dec(&br->br_count);
-+			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;
-+
-+	h_parent = wh->d_parent; /* dir inode is locked */
-+	h_dir = h_parent->d_inode;
-+	IMustLock(h_dir);
-+
-+	br = au_sbr(sb, bindex);
-+	h_path.mnt = br->br_mnt;
-+	wbr = br->br_wbr;
-+	wbr_wh_read_lock(wbr);
-+	if (wbr->wbr_whbase) {
-+		err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
-+		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);
-+
-+ 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 = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
-+	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	= br->br_mnt
-+		};
-+		err = do_unlink_wh(au_h_iptr(dentry->d_inode, 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(h_dentry->d_inode, 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 = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
-+		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) && !wh_dentry->d_inode) {
-+		err = link_or_create_wh(sb, bindex, wh_dentry);
-+		if (!err)
-+			au_set_dbwh(dentry, bindex);
-+		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 *tpos;
-+	struct hlist_node *pos;
-+	struct au_vdir_destr *str;
-+
-+	err = -ENOMEM;
-+	p = __getname_gfp(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(tpos, pos, head, wh_hash) {
-+			if (tpos->wh_bindex != bindex)
-+				continue;
-+
-+			str = &tpos->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;
-+		}
-+	}
-+	__putname(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 = kmalloc(sizeof(*whtmp), gfp);
-+	if (unlikely(!whtmp)) {
-+		whtmp = ERR_PTR(-ENOMEM);
-+		goto out;
-+	}
-+
-+	whtmp->dir = NULL;
-+	whtmp->wh_dentry = NULL;
-+	/* 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)) {
-+		kfree(whtmp);
-+		whtmp = ERR_PTR(err);
-+	}
-+
-+ out:
-+	return whtmp;
-+}
-+
-+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
-+{
-+	dput(whtmp->wh_dentry);
-+	iput(whtmp->dir);
-+	au_nhash_wh_free(&whtmp->whlist);
-+	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;
-+	struct path h_tmp;
-+	struct inode *wh_inode, *h_dir;
-+	struct au_branch *br;
-+
-+	h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
-+	IMustLock(h_dir);
-+
-+	br = au_sbr(dir->i_sb, bindex);
-+	wh_inode = wh_dentry->d_inode;
-+	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 = br->br_mnt;
-+		err = vfsub_rmdir(h_dir, &h_tmp);
-+		/* d_drop(h_dentry); */
-+	}
-+
-+	if (!err) {
-+		if (au_ibstart(dir) == bindex) {
-+			au_cpup_attr_timesizes(dir);
-+			drop_nlink(dir);
-+		}
-+		return 0; /* success */
-+	}
-+
-+	pr_warning("failed removing %.*s(%d), ignored\n",
-+		   AuDLNPair(wh_dentry), err);
-+	return err;
-+}
-+
-+static void call_rmdir_whtmp(void *args)
-+{
-+	int err;
-+	struct au_whtmp_rmdir *a = args;
-+	struct super_block *sb;
-+	struct dentry *h_parent;
-+	struct inode *h_dir;
-+	struct au_branch *br;
-+	struct au_hinode *hdir;
-+
-+	/* rmdir by nfsd may cause deadlock with this i_mutex */
-+	/* mutex_lock(&a->dir->i_mutex); */
-+	sb = a->dir->i_sb;
-+	si_noflush_read_lock(sb);
-+	err = au_test_ro(sb, a->bindex, NULL);
-+	if (unlikely(err))
-+		goto out;
-+
-+	err = -EIO;
-+	br = au_sbr(sb, a->bindex);
-+	ii_write_lock_parent(a->dir);
-+	h_parent = dget_parent(a->wh_dentry);
-+	h_dir = h_parent->d_inode;
-+	hdir = au_hi(a->dir, a->bindex);
-+	au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
-+	err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
-+	if (!err) {
-+		err = mnt_want_write(br->br_mnt);
-+		if (!err) {
-+			err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
-+					     &a->whlist);
-+			mnt_drop_write(br->br_mnt);
-+		}
-+	}
-+	au_hn_imtx_unlock(hdir);
-+	dput(h_parent);
-+	ii_write_unlock(a->dir);
-+
-+ out:
-+	/* mutex_unlock(&a->dir->i_mutex); */
-+	au_nwt_done(&au_sbi(sb)->si_nowait);
-+	si_read_unlock(sb);
-+	au_whtmp_rmdir_free(a);
-+	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;
-+
-+	IMustLock(dir);
-+
-+	/* all post-process will be done in do_rmdir_whtmp(). */
-+	args->dir = au_igrab(dir);
-+	args->bindex = bindex;
-+	args->wh_dentry = dget(wh_dentry);
-+	wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
-+	if (unlikely(wkq_err)) {
-+		pr_warning("rmdir error %.*s (%d), ignored\n",
-+			   AuDLNPair(wh_dentry), wkq_err);
-+		au_whtmp_rmdir_free(args);
-+	}
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/whout.h linux-2.6.33.1/fs/aufs/whout.h
---- linux-2.6.33.1-vanilla/fs/aufs/whout.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/whout.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,87 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * whiteout for logical deletion and opaque directory
-+ */
-+
-+#ifndef __AUFS_WHOUT_H__
-+#define __AUFS_WHOUT_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/aufs_type.h>
-+#include "dir.h"
-+
-+/* whout.c */
-+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
-+struct au_branch;
-+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
-+	       struct au_branch *br, int try_sio);
-+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
-+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 dentry *h_parent, 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)	{ (flags) |= AuDiropq_##name; }
-+#define au_fclr_diropq(flags, name)	{ (flags) &= ~AuDiropq_##name; }
-+
-+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;
-+	aufs_bindex_t bindex;
-+	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 -Nur linux-2.6.33.1-vanilla/fs/aufs/wkq.c linux-2.6.33.1/fs/aufs/wkq.c
---- linux-2.6.33.1-vanilla/fs/aufs/wkq.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/wkq.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,183 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * workqueue for asynchronous/super-io operations
-+ * todo: try new dredential scheme
-+ */
-+
-+#include <linux/module.h>
-+#include "aufs.h"
-+
-+/* internal workqueue named AUFS_WKQ_NAME */
-+static struct workqueue_struct *au_wkq;
-+
-+struct au_wkinfo {
-+	struct work_struct wk;
-+	struct super_block *sb;
-+
-+	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);
-+
-+	wkinfo->func(wkinfo->args);
-+	if (au_ftest_wkq(wkinfo->flags, WAIT))
-+		complete(wkinfo->comp);
-+	else {
-+		kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
-+		module_put(THIS_MODULE);
-+		kfree(wkinfo);
-+	}
-+}
-+
-+/*
-+ * Since struct completion is large, try allocating it dynamically.
-+ */
-+#if 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)
-+{
-+	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, int do_wait)
-+{
-+	au_dbg_verify_kthread();
-+	if (do_wait) {
-+		INIT_WORK_ON_STACK(&wkinfo->wk, wkq_func);
-+		queue_work(au_wkq, &wkinfo->wk);
-+	} else {
-+		INIT_WORK(&wkinfo->wk, wkq_func);
-+		schedule_work(&wkinfo->wk);
-+	}
-+}
-+
-+int au_wkq_wait(au_wkq_func_t func, void *args)
-+{
-+	int err;
-+	AuWkqCompDeclare(comp);
-+	struct au_wkinfo wkinfo = {
-+		.flags	= AuWkq_WAIT,
-+		.func	= func,
-+		.args	= args
-+	};
-+
-+	err = au_wkq_comp_alloc(&wkinfo, &comp);
-+	if (!err) {
-+		au_wkq_run(&wkinfo, AuWkq_WAIT);
-+		/* no timeout, no interrupt */
-+		wait_for_completion(wkinfo.comp);
-+		au_wkq_comp_free(comp);
-+		destroy_work_on_stack(&wkinfo.wk);
-+	}
-+
-+	return err;
-+
-+}
-+
-+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
-+{
-+	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->sb = sb;
-+		wkinfo->flags = !AuWkq_WAIT;
-+		wkinfo->func = func;
-+		wkinfo->args = args;
-+		wkinfo->comp = NULL;
-+		kobject_get(&au_sbi(sb)->si_kobj);
-+		__module_get(THIS_MODULE);
-+
-+		au_wkq_run(wkinfo, !AuWkq_WAIT);
-+	} else {
-+		err = -ENOMEM;
-+		atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
-+	}
-+
-+	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)
-+{
-+	au_wkq = create_workqueue(AUFS_WKQ_NAME);
-+	return 0;
-+}
-diff -Nur linux-2.6.33.1-vanilla/fs/aufs/wkq.h linux-2.6.33.1/fs/aufs/wkq.h
---- linux-2.6.33.1-vanilla/fs/aufs/wkq.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/wkq.h	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,84 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * workqueue for asynchronous/super-io operations
-+ * todo: try new credentials management scheme
-+ */
-+
-+#ifndef __AUFS_WKQ_H__
-+#define __AUFS_WKQ_H__
-+
-+#ifdef __KERNEL__
-+
-+#include <linux/sched.h>
-+#include <linux/wait.h>
-+#include <linux/aufs_type.h>
-+
-+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 au_ftest_wkq(flags, name)	((flags) & AuWkq_##name)
-+#define au_fset_wkq(flags, name)	{ (flags) |= AuWkq_##name; }
-+#define au_fclr_wkq(flags, name)	{ (flags) &= ~AuWkq_##name; }
-+
-+/* wkq.c */
-+int au_wkq_wait(au_wkq_func_t func, void *args);
-+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
-+void au_nwt_init(struct au_nowait_tasks *nwt);
-+int __init au_wkq_init(void);
-+void au_wkq_fin(void);
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static inline int au_test_wkq(struct task_struct *tsk)
-+{
-+	return !tsk->mm
-+		&& !strncmp(tsk->comm, AUFS_WKQ_NAME "/",
-+			    sizeof(AUFS_WKQ_NAME));
-+}
-+
-+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
-+{
-+	if (!atomic_dec_return(&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 -Nur linux-2.6.33.1-vanilla/fs/aufs/xino.c linux-2.6.33.1/fs/aufs/xino.c
---- linux-2.6.33.1-vanilla/fs/aufs/xino.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.33.1/fs/aufs/xino.c	2010-04-05 16:53:27.000000000 +0200
-@@ -0,0 +1,1202 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+/*
-+ * external inode number translation table and bitmap
-+ */
-+
-+#include <linux/file.h>
-+#include <linux/seq_file.h>
-+#include <linux/uaccess.h>
-+#include "aufs.h"
-+
-+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
-+		   loff_t *pos)
-+{
-+	ssize_t err;
-+	mm_segment_t oldfs;
-+
-+	oldfs = get_fs();
-+	set_fs(KERNEL_DS);
-+	do {
-+		/* todo: signal_pending? */
-+		err = func(file, (char __user *)buf, size, pos);
-+	} while (err == -EAGAIN || err == -EINTR);
-+	set_fs(oldfs);
-+
-+#if 0 /* reserved for future use */
-+	if (err > 0)
-+		fsnotify_access(file->f_dentry);
-+#endif
-+
-+	return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
-+			      size_t size, loff_t *pos)
-+{
-+	ssize_t err;
-+	mm_segment_t oldfs;
-+
-+	oldfs = get_fs();
-+	set_fs(KERNEL_DS);
-+	/* lockdep_off(); */
-+	do {
-+		/* todo: signal_pending? */
-+		err = func(file, (const char __user *)buf, size, pos);
-+	} while (err == -EAGAIN || err == -EINTR);
-+	/* lockdep_on(); */
-+	set_fs(oldfs);
-+
-+#if 0 /* reserved for future use */
-+	if (err > 0)
-+		fsnotify_modify(file->f_dentry);
-+#endif
-+
-+	return err;
-+}
-+
-+struct do_xino_fwrite_args {
-+	ssize_t *errp;
-+	au_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);
-+}
-+
-+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
-+		    loff_t *pos)
-+{
-+	ssize_t err;
-+
-+	/* todo: signal block and no wkq? */
-+	/* todo: new credential scheme */
-+	/*
-+	 * it breaks RLIMIT_FSIZE and normal user's limit,
-+	 * users should care about quota and real 'filesystem full.'
-+	 */
-+	if (!au_test_wkq(current)) {
-+		int wkq_err;
-+		struct do_xino_fwrite_args args = {
-+			.errp	= &err,
-+			.func	= func,
-+			.file	= file,
-+			.buf	= buf,
-+			.size	= size,
-+			.pos	= pos
-+		};
-+
-+		wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
-+		if (unlikely(wkq_err))
-+			err = wkq_err;
-+	} else
-+		err = do_xino_fwrite(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;
-+	struct qstr *name;
-+	struct path path;
-+	int err;
-+
-+	base = base_file->f_dentry;
-+	parent = base->d_parent; /* dir inode is locked */
-+	dir = parent->d_inode;
-+	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("%.*s lookup err %ld\n",
-+		       AuLNPair(name), 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("%.*s create err %d\n", AuLNPair(name), err);
-+		goto out_dput;
-+	}
-+
-+	path.mnt = base_file->f_vfsmnt;
-+	file = vfsub_dentry_open(&path,
-+				 O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
-+	if (IS_ERR(file)) {
-+		pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
-+		goto out_dput;
-+	}
-+
-+	err = vfsub_unlink(dir, &file->f_path, /*force*/0);
-+	if (unlikely(err)) {
-+		pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
-+		goto out_fput;
-+	}
-+
-+	if (copy_src) {
-+		/* no one can touch copy_src xino */
-+		err = au_copy_file(file, copy_src,
-+				   i_size_read(copy_src->f_dentry->d_inode));
-+		if (unlikely(err)) {
-+			pr_err("%.*s copy err %d\n", AuLNPair(name), 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(sb->s_root->d_inode, bindex);
-+		au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
-+	} else {
-+		ldir->parent = dget_parent(xino->f_dentry);
-+		ldir->mtx = &ldir->parent->d_inode->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;
-+	aufs_bindex_t bi, bend;
-+	struct au_branch *br;
-+	struct file *new_xino, *file;
-+	struct super_block *h_sb;
-+	struct au_xino_lock_dir ldir;
-+
-+	err = -EINVAL;
-+	bend = au_sbend(sb);
-+	if (unlikely(bindex < 0 || bend < bindex))
-+		goto out;
-+	br = au_sbr(sb, bindex);
-+	file = br->br_xino.xi_file;
-+	if (!file)
-+		goto out;
-+
-+	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))
-+		goto out;
-+	err = 0;
-+	fput(file);
-+	br->br_xino.xi_file = new_xino;
-+
-+	h_sb = br->br_mnt->mnt_sb;
-+	for (bi = 0; bi <= bend; bi++) {
-+		if (unlikely(bi == bindex))
-+			continue;
-+		br = au_sbr(sb, bi);
-+		if (br->br_mnt->mnt_sb != h_sb)
-+			continue;
-+
-+		fput(br->br_xino.xi_file);
-+		br->br_xino.xi_file = new_xino;
-+		get_file(new_xino);
-+	}
-+
-+ 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 = sb->s_root->d_inode;
-+	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);
-+	if (!err
-+	    && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
-+	    >= br->br_xino_upper)
-+		br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
-+
-+	ii_read_unlock(dir);
-+	if (unlikely(err))
-+		pr_warning("err b%d, (%d)\n", bindex, err);
-+	atomic_dec(&br->br_xino_running);
-+	atomic_dec(&br->br_count);
-+	au_nwt_done(&au_sbi(sb)->si_nowait);
-+	si_write_unlock(sb);
-+	kfree(args);
-+}
-+
-+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
-+{
-+	struct xino_do_trunc_args *args;
-+	int wkq_err;
-+
-+	if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
-+	    < br->br_xino_upper)
-+		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_args;
-+	}
-+
-+	atomic_inc_return(&br->br_count);
-+	args->sb = sb;
-+	args->br = br;
-+	wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
-+	if (!wkq_err)
-+		return; /* success */
-+
-+	pr_err("wkq %d\n", wkq_err);
-+	atomic_dec_return(&br->br_count);
-+
-+ out_args:
-+	kfree(args);
-+ out:
-+	atomic_dec_return(&br->br_xino_running);
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static int au_xino_do_write(au_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(br->br_mnt->mnt_sb))
-+			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 (i_size_read(xib->f_dentry->d_inode) >= 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;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
-+		   ino_t ino)
-+{
-+	int err, bit;
-+	unsigned long pindex;
-+	struct au_sbinfo *sbinfo;
-+
-+	if (!au_opt_test(au_mntflags(sb), XINO))
-+		return 0;
-+
-+	err = 0;
-+	if (ino) {
-+		sbinfo = au_sbi(sb);
-+		xib_calc_bit(ino, &pindex, &bit);
-+		AuDebugOn(page_bits <= bit);
-+		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);
-+	}
-+
-+	if (!err)
-+		err = au_xino_write(sb, bindex, h_ino, 0);
-+	return err;
-+}
-+
-+/* get an unused inode number from bitmap */
-+ino_t au_xino_new_ino(struct super_block *sb)
-+{
-+	ino_t ino;
-+	unsigned long *p, pindex, ul, pend;
-+	struct au_sbinfo *sbinfo;
-+	struct file *file;
-+	int free_bit, err;
-+
-+	if (!au_opt_test(au_mntflags(sb), XINO))
-+		return iunique(sb, AUFS_FIRST_INO);
-+
-+	sbinfo = au_sbi(sb);
-+	mutex_lock(&sbinfo->si_xib_mtx);
-+	p = sbinfo->si_xib_buf;
-+	free_bit = sbinfo->si_xib_next_bit;
-+	if (free_bit < page_bits && !test_bit(free_bit, p))
-+		goto out; /* success */
-+	free_bit = find_first_zero_bit(p, page_bits);
-+	if (free_bit < page_bits)
-+		goto out; /* success */
-+
-+	pindex = sbinfo->si_xib_last_pindex;
-+	for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
-+		err = xib_pindex(sb, ul);
-+		if (unlikely(err))
-+			goto out_err;
-+		free_bit = find_first_zero_bit(p, page_bits);
-+		if (free_bit < page_bits)
-+			goto out; /* success */
-+	}
-+
-+	file = sbinfo->si_xib;
-+	pend = i_size_read(file->f_dentry->d_inode) / 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++;
-+	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 (i_size_read(file->f_dentry->d_inode) < 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;
-+	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,
-+			       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 */
-+	h_parent = dget_parent(file->f_dentry);
-+	h_dir = h_parent->d_inode;
-+	mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
-+	/* mnt_want_write() is unnecessary here */
-+	err = vfsub_unlink(h_dir, &file->f_path, /*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_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 @bend.
-+ */
-+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
-+			aufs_bindex_t bend)
-+{
-+	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 <= bend; 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 bend, bindex;
-+	struct au_branch *shared_br, *b;
-+	struct file *file;
-+	struct super_block *tgt_sb;
-+
-+	shared_br = NULL;
-+	bend = au_sbend(sb);
-+	if (do_test) {
-+		tgt_sb = br->br_mnt->mnt_sb;
-+		for (bindex = 0; bindex <= bend; bindex++) {
-+			b = au_sbr(sb, bindex);
-+			if (tgt_sb == b->br_mnt->mnt_sb) {
-+				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 (!err)
-+		return 0; /* success */
-+
-+
-+ 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;
-+	au_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 = i_size_read(file->f_dentry->d_inode);
-+	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, bend;
-+	void *page;
-+
-+	err = -ENOMEM;
-+	page = (void *)__get_free_page(GFP_NOFS);
-+	if (unlikely(!page))
-+		goto out;
-+
-+	err = 0;
-+	bend = au_sbend(sb);
-+	for (bindex = 0; !err && bindex <= bend; 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);
-+	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 (i_size_read(file->f_dentry->d_inode) <= 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
-+ */
-+static au_readf_t find_readf(struct file *h_file)
-+{
-+	const struct file_operations *fop = h_file->f_op;
-+
-+	if (fop) {
-+		if (fop->read)
-+			return fop->read;
-+		if (fop->aio_read)
-+			return do_sync_read;
-+	}
-+	return ERR_PTR(-ENOSYS);
-+}
-+
-+static au_writef_t find_writef(struct file *h_file)
-+{
-+	const struct file_operations *fop = h_file->f_op;
-+
-+	if (fop) {
-+		if (fop->write)
-+			return fop->write;
-+		if (fop->aio_write)
-+			return do_sync_write;
-+	}
-+	return ERR_PTR(-ENOSYS);
-+}
-+
-+/* 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;
-+	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 = find_readf(file);
-+	sbinfo->si_xwrite = find_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 (i_size_read(file->f_dentry->d_inode) < 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:
-+	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, bend;
-+	struct au_branch *br;
-+
-+	bend = au_sbend(sb);
-+	for (bindex = 0; bindex <= bend; 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, bend, bshared;
-+	struct {
-+		struct file *old, *new;
-+	} *fpair, *p;
-+	struct au_branch *br;
-+	struct inode *inode;
-+	au_writef_t writef;
-+
-+	SiMustWriteLock(sb);
-+
-+	err = -ENOMEM;
-+	bend = au_sbend(sb);
-+	fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
-+	if (unlikely(!fpair))
-+		goto out;
-+
-+	inode = sb->s_root->d_inode;
-+	ino = AUFS_ROOT_INO;
-+	writef = au_sbi(sb)->si_xwrite;
-+	for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
-+		br = au_sbr(sb, bindex);
-+		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 */
-+			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 <= bend; 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 <= bend; bindex++, p++)
-+		if (p->new)
-+			fput(p->new);
-+		else
-+			break;
-+	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_dentry);
-+	if (remount) {
-+		skip = 0;
-+		dname = &xino->file->f_dentry->d_name;
-+		cur_xino = sbinfo->si_xib;
-+		if (cur_xino) {
-+			cur_parent = dget_parent(cur_xino->f_dentry);
-+			cur_name = &cur_xino->f_dentry->d_name;
-+			skip = (cur_parent == parent
-+				&& dname->len == cur_name->len
-+				&& !memcmp(dname->name, cur_name->name,
-+					   dname->len));
-+			dput(cur_parent);
-+		}
-+		if (skip)
-+			goto out;
-+	}
-+
-+	au_opt_set(sbinfo->si_mntflags, XINO);
-+	dir = parent->d_inode;
-+	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);
-+
-+ 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 bend, bindex, bwr;
-+
-+	br = NULL;
-+	bend = au_sbend(sb);
-+	bwr = -1;
-+	for (bindex = 0; bindex <= bend; bindex++) {
-+		br = au_sbr(sb, bindex);
-+		if (au_br_writable(br->br_perm)
-+		    && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
-+			bwr = bindex;
-+			break;
-+		}
-+	}
-+
-+	if (bwr >= 0) {
-+		file = ERR_PTR(-ENOMEM);
-+		page = __getname_gfp(GFP_NOFS);
-+		if (unlikely(!page))
-+			goto out;
-+		path.mnt = br->br_mnt;
-+		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);
-+		}
-+		__putname(page);
-+	} else {
-+		file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
-+		if (IS_ERR(file))
-+			goto out;
-+		h_sb = file->f_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 < 0))
-+		goto out;
-+
-+	err = 0;
-+#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 -Nur linux-2.6.33.1-vanilla/fs/Kconfig linux-2.6.33.1/fs/Kconfig
---- linux-2.6.33.1-vanilla/fs/Kconfig	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/Kconfig	2010-04-05 16:54:40.000000000 +0200
-@@ -188,6 +188,7 @@
- source "fs/sysv/Kconfig"
- source "fs/ufs/Kconfig"
- source "fs/exofs/Kconfig"
-+source "fs/aufs/Kconfig"
- 
- endif # MISC_FILESYSTEMS
- 
-diff -Nur linux-2.6.33.1-vanilla/fs/Makefile linux-2.6.33.1/fs/Makefile
---- linux-2.6.33.1-vanilla/fs/Makefile	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/Makefile	2010-04-05 16:54:40.000000000 +0200
-@@ -124,3 +124,4 @@
- obj-$(CONFIG_GFS2_FS)           += gfs2/
- obj-$(CONFIG_EXOFS_FS)          += exofs/
- obj-$(CONFIG_CEPH_FS)		+= ceph/
-+obj-$(CONFIG_AUFS_FS)           += aufs/
-diff -Nur linux-2.6.33.1-vanilla/fs/namei.c linux-2.6.33.1/fs/namei.c
---- linux-2.6.33.1-vanilla/fs/namei.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/namei.c	2010-04-05 16:54:44.000000000 +0200
-@@ -349,6 +349,7 @@
- 
- 	return 0;
- }
-+EXPORT_SYMBOL(deny_write_access);
- 
- /**
-  * path_get - get a reference to a path
-@@ -1207,7 +1208,7 @@
-  * needs parent already locked. Doesn't follow mounts.
-  * SMP-safe.
-  */
--static struct dentry *lookup_hash(struct nameidata *nd)
-+struct dentry *lookup_hash(struct nameidata *nd)
- {
- 	int err;
- 
-@@ -1216,8 +1217,9 @@
- 		return ERR_PTR(err);
- 	return __lookup_hash(&nd->last, nd->path.dentry, nd);
- }
-+EXPORT_SYMBOL(lookup_hash);
- 
--static int __lookup_one_len(const char *name, struct qstr *this,
-+int __lookup_one_len(const char *name, struct qstr *this,
- 		struct dentry *base, int len)
- {
- 	unsigned long hash;
-@@ -1238,6 +1240,7 @@
- 	this->hash = end_name_hash(hash);
- 	return 0;
- }
-+EXPORT_SYMBOL(__lookup_one_len);
- 
- /**
-  * lookup_one_len - filesystem helper to lookup single pathname component
-diff -Nur linux-2.6.33.1-vanilla/fs/namespace.c linux-2.6.33.1/fs/namespace.c
---- linux-2.6.33.1-vanilla/fs/namespace.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/namespace.c	2010-04-05 16:54:44.000000000 +0200
-@@ -39,6 +39,7 @@
- 
- /* spinlock for vfsmount related operations, inplace of dcache_lock */
- __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
-+EXPORT_SYMBOL(vfsmount_lock);
- 
- static int event;
- static DEFINE_IDA(mnt_id_ida);
-diff -Nur linux-2.6.33.1-vanilla/fs/notify/group.c linux-2.6.33.1/fs/notify/group.c
---- linux-2.6.33.1-vanilla/fs/notify/group.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/notify/group.c	2010-04-05 16:54:44.000000000 +0200
-@@ -22,6 +22,7 @@
- #include <linux/srcu.h>
- #include <linux/rculist.h>
- #include <linux/wait.h>
-+#include <linux/module.h>
- 
- #include <linux/fsnotify_backend.h>
- #include "fsnotify.h"
-@@ -169,6 +170,7 @@
- 	fsnotify_recalc_global_mask();
- 	fsnotify_destroy_group(group);
- }
-+EXPORT_SYMBOL(fsnotify_put_group);
- 
- /*
-  * Simply run the fsnotify_groups list and find a group which matches
-@@ -252,3 +254,4 @@
- 
- 	return group;
- }
-+EXPORT_SYMBOL(fsnotify_obtain_group);
-diff -Nur linux-2.6.33.1-vanilla/fs/notify/inode_mark.c \
                linux-2.6.33.1/fs/notify/inode_mark.c
---- linux-2.6.33.1-vanilla/fs/notify/inode_mark.c	2010-03-15 17:09:39.000000000 \
                +0100
-+++ linux-2.6.33.1/fs/notify/inode_mark.c	2010-04-05 16:54:44.000000000 +0200
-@@ -106,6 +106,7 @@
- 	if (atomic_dec_and_test(&entry->refcnt))
- 		entry->free_mark(entry);
- }
-+EXPORT_SYMBOL(fsnotify_put_mark);
- 
- /*
-  * Recalculate the mask of events relevant to a given inode locked.
-@@ -216,6 +217,7 @@
- 	if (unlikely(atomic_dec_and_test(&group->num_marks)))
- 		fsnotify_final_destroy_group(group);
- }
-+EXPORT_SYMBOL(fsnotify_destroy_mark_by_entry);
- 
- /*
-  * Given a group, destroy all of the marks associated with that group.
-@@ -282,6 +284,7 @@
- 	}
- 	return NULL;
- }
-+EXPORT_SYMBOL(fsnotify_find_mark_entry);
- 
- /*
-  * Nothing fancy, just initialize lists and locks and counters.
-@@ -298,6 +301,7 @@
- 	entry->inode = NULL;
- 	entry->free_mark = free_mark;
- }
-+EXPORT_SYMBOL(fsnotify_init_mark);
- 
- /*
-  * Attach an initialized mark entry to a given group and inode.
-@@ -353,6 +357,7 @@
- 
- 	return ret;
- }
-+EXPORT_SYMBOL(fsnotify_add_mark);
- 
- /**
-  * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
-diff -Nur linux-2.6.33.1-vanilla/fs/open.c linux-2.6.33.1/fs/open.c
---- linux-2.6.33.1-vanilla/fs/open.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/open.c	2010-04-05 16:54:44.000000000 +0200
-@@ -226,6 +226,7 @@
- 	mutex_unlock(&dentry->d_inode->i_mutex);
- 	return ret;
- }
-+EXPORT_SYMBOL(do_truncate);
- 
- static long do_sys_truncate(const char __user *pathname, loff_t length)
- {
-diff -Nur linux-2.6.33.1-vanilla/fs/splice.c linux-2.6.33.1/fs/splice.c
---- linux-2.6.33.1-vanilla/fs/splice.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/fs/splice.c	2010-04-05 16:54:44.000000000 +0200
-@@ -1053,8 +1053,8 @@
- /*
-  * 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);
-@@ -1077,13 +1077,14 @@
- 
- 	return splice_write(pipe, out, ppos, len, flags);
- }
-+EXPORT_SYMBOL(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);
-@@ -1103,6 +1104,7 @@
- 
- 	return splice_read(in, ppos, pipe, len, flags);
- }
-+EXPORT_SYMBOL(do_splice_to);
- 
- /**
-  * splice_direct_to_actor - splices data directly between two non-pipes
-diff -Nur linux-2.6.33.1-vanilla/include/linux/aufs_type.h \
                linux-2.6.33.1/include/linux/aufs_type.h
---- linux-2.6.33.1-vanilla/include/linux/aufs_type.h	1970-01-01 01:00:00.000000000 \
                +0100
-+++ linux-2.6.33.1/include/linux/aufs_type.h	2010-04-05 16:53:31.000000000 +0200
-@@ -0,0 +1,198 @@
-+/*
-+ * Copyright (C) 2005-2010 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
-+ */
-+
-+#ifndef __AUFS_TYPE_H__
-+#define __AUFS_TYPE_H__
-+
-+#include <linux/ioctl.h>
-+/* for those who didn't "make headers_install" */
-+#ifdef __KERNEL__
-+#include <linux/kernel.h>
-+#endif
-+#include <linux/limits.h>
-+#include <linux/types.h>
-+
-+#define AUFS_VERSION	"2-standalone.tree-33-20100405"
-+
-+/* 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 __s8 aufs_bindex_t;
-+#define AUFS_BRANCH_MAX 127
-+#else
-+typedef __s16 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_NAME		"aufs"
-+#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 */
-+#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_TRUNC_INIT	64 /* blocks */
-+#define AUFS_XINO_TRUNC_STEP	4  /* blocks */
-+#define AUFS_DIRWH_DEF		3
-+#define AUFS_RDCACHE_DEF	10 /* seconds */
-+#define AUFS_RDBLK_DEF		512 /* bytes */
-+#define AUFS_RDHASH_DEF		32
-+#define AUFS_WKQ_NAME		AUFS_NAME "d"
-+#define AUFS_MFS_SECOND_DEF	30 /* seconds */
-+#define AUFS_PLINK_WARN		100 /* number of plinks */
-+
-+#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 permission */
-+#define AUFS_BRPERM_RW		"rw"
-+#define AUFS_BRPERM_RO		"ro"
-+#define AUFS_BRPERM_RR		"rr"
-+#define AUFS_BRPERM_WH		"wh"
-+#define AUFS_BRPERM_NLWH	"nolwh"
-+#define AUFS_BRPERM_ROWH	AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
-+#define AUFS_BRPERM_RRWH	AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
-+#define AUFS_BRPERM_RWNLWH	AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
-+
-+/* ---------------------------------------------------------------------- */
-+
-+/* ioctl */
-+enum {
-+	AuCtl_PLINK_MAINT,
-+	AuCtl_PLINK_CLEAN,
-+
-+	/* readdir in userspace */
-+	AuCtl_RDU,
-+	AuCtl_RDU_INO,
-+
-+	/* pathconf wrapper */
-+	AuCtl_WBR_FD
-+};
-+
-+/* 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)))
-+#define __packed			__attribute__((packed))
-+#endif
-+
-+struct au_rdu_cookie {
-+	__u64		h_pos;
-+	__s16		bindex;
-+	__u8		flags;
-+	__u8		pad;
-+	__u32		generation;
-+} __aligned(8);
-+
-+struct au_rdu_ent {
-+	__u64		ino;
-+	__s16		bindex;
-+	__u8		type;
-+	__u8		nlen;
-+	__u8		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(__u64));
-+}
-+
-+union au_rdu_ent_ul {
-+	struct au_rdu_ent __user	*e;
-+	unsigned long			ul;
-+};
-+
-+enum {
-+	AufsCtlRduV_SZ,
-+	AufsCtlRduV_SZ_PTR,
-+	AufsCtlRduV_End
-+};
-+
-+struct aufs_rdu {
-+	/* input */
-+	union {
-+		__u64		sz;	/* AuCtl_RDU */
-+		__u64		nent;	/* AuCtl_RDU_INO */
-+	};
-+	union au_rdu_ent_ul	ent;
-+	__u16			verify[AufsCtlRduV_End];
-+
-+	/* input/output */
-+	__u32			blk;
-+
-+	/* output */
-+	union au_rdu_ent_ul	tail;
-+	/* number of entries which were added in a single call */
-+	__u64			rent;
-+	__u8			full;
-+	__u8			shwh;
-+
-+	struct au_rdu_cookie	cookie;
-+} __aligned(8);
-+
-+#define AuCtlType		'A'
-+#define AUFS_CTL_PLINK_MAINT	_IO(AuCtlType, AuCtl_PLINK_MAINT)
-+#define AUFS_CTL_PLINK_CLEAN	_IO(AuCtlType, AuCtl_PLINK_CLEAN)
-+#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		_IO(AuCtlType, AuCtl_WBR_FD)
-+
-+#endif /* __AUFS_TYPE_H__ */
-diff -Nur linux-2.6.33.1-vanilla/include/linux/Kbuild \
                linux-2.6.33.1/include/linux/Kbuild
---- linux-2.6.33.1-vanilla/include/linux/Kbuild	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/include/linux/Kbuild	2010-04-05 16:54:40.000000000 +0200
-@@ -34,6 +34,7 @@
- header-y += atmsap.h
- header-y += atmsvc.h
- header-y += atm_zatm.h
-+header-y += aufs_type.h
- header-y += auto_fs4.h
- header-y += ax25.h
- header-y += b1lli.h
-diff -Nur linux-2.6.33.1-vanilla/include/linux/namei.h \
                linux-2.6.33.1/include/linux/namei.h
---- linux-2.6.33.1-vanilla/include/linux/namei.h	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/include/linux/namei.h	2010-04-05 16:54:34.000000000 +0200
-@@ -73,6 +73,9 @@
- extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry \
                *dentry,
- 		int (*open)(struct inode *, struct file *));
- 
-+extern struct dentry *lookup_hash(struct nameidata *nd);
-+extern int __lookup_one_len(const char *name, struct qstr *this,
-+			    struct dentry *base, int len);
- extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
- 
- extern int follow_down(struct path *);
-diff -Nur linux-2.6.33.1-vanilla/include/linux/splice.h \
                linux-2.6.33.1/include/linux/splice.h
---- linux-2.6.33.1-vanilla/include/linux/splice.h	2010-03-15 17:09:39.000000000 \
                +0100
-+++ linux-2.6.33.1/include/linux/splice.h	2010-04-05 16:54:34.000000000 +0200
-@@ -82,4 +82,10 @@
- extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
- 				      splice_direct_actor *);
- 
-+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 -Nur linux-2.6.33.1-vanilla/security/commoncap.c \
                linux-2.6.33.1/security/commoncap.c
---- linux-2.6.33.1-vanilla/security/commoncap.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/security/commoncap.c	2010-04-05 16:54:44.000000000 +0200
-@@ -946,3 +946,4 @@
- 	}
- 	return ret;
- }
-+EXPORT_SYMBOL(cap_file_mmap);
-diff -Nur linux-2.6.33.1-vanilla/security/device_cgroup.c \
                linux-2.6.33.1/security/device_cgroup.c
---- linux-2.6.33.1-vanilla/security/device_cgroup.c	2010-03-15 17:09:39.000000000 \
                +0100
-+++ linux-2.6.33.1/security/device_cgroup.c	2010-04-05 16:54:44.000000000 +0200
-@@ -514,6 +514,7 @@
- 
- 	return -EPERM;
- }
-+EXPORT_SYMBOL(devcgroup_inode_permission);
- 
- int devcgroup_inode_mknod(int mode, dev_t dev)
- {
-diff -Nur linux-2.6.33.1-vanilla/security/security.c \
                linux-2.6.33.1/security/security.c
---- linux-2.6.33.1-vanilla/security/security.c	2010-03-15 17:09:39.000000000 +0100
-+++ linux-2.6.33.1/security/security.c	2010-04-05 16:54:44.000000000 +0200
-@@ -404,6 +404,7 @@
- 		return 0;
- 	return security_ops->path_mkdir(path, dentry, mode);
- }
-+EXPORT_SYMBOL(security_path_mkdir);
- 
- int security_path_rmdir(struct path *path, struct dentry *dentry)
- {
-@@ -411,6 +412,7 @@
- 		return 0;
- 	return security_ops->path_rmdir(path, dentry);
- }
-+EXPORT_SYMBOL(security_path_rmdir);
- 
- int security_path_unlink(struct path *path, struct dentry *dentry)
- {
-@@ -418,6 +420,7 @@
- 		return 0;
- 	return security_ops->path_unlink(path, dentry);
- }
-+EXPORT_SYMBOL(security_path_unlink);
- 
- int security_path_symlink(struct path *path, struct dentry *dentry,
- 			  const char *old_name)
-@@ -426,6 +429,7 @@
- 		return 0;
- 	return security_ops->path_symlink(path, dentry, old_name);
- }
-+EXPORT_SYMBOL(security_path_symlink);
- 
- int security_path_link(struct dentry *old_dentry, struct path *new_dir,
- 		       struct dentry *new_dentry)
-@@ -434,6 +438,7 @@
- 		return 0;
- 	return security_ops->path_link(old_dentry, new_dir, new_dentry);
- }
-+EXPORT_SYMBOL(security_path_link);
- 
- int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
- 			 struct path *new_dir, struct dentry *new_dentry)
-@@ -444,6 +449,7 @@
- 	return security_ops->path_rename(old_dir, old_dentry, new_dir,
- 					 new_dentry);
- }
-+EXPORT_SYMBOL(security_path_rename);
- 
- int security_path_truncate(struct path *path, loff_t length,
- 			   unsigned int time_attrs)
-@@ -452,6 +458,7 @@
- 		return 0;
- 	return security_ops->path_truncate(path, length, time_attrs);
- }
-+EXPORT_SYMBOL(security_path_truncate);
- 
- int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- 			mode_t mode)
-@@ -460,6 +467,7 @@
- 		return 0;
- 	return security_ops->path_chmod(dentry, mnt, mode);
- }
-+EXPORT_SYMBOL(security_path_chmod);
- 
- int security_path_chown(struct path *path, uid_t uid, gid_t gid)
- {
-@@ -467,6 +475,7 @@
- 		return 0;
- 	return security_ops->path_chown(path, uid, gid);
- }
-+EXPORT_SYMBOL(security_path_chown);
- 
- int security_path_chroot(struct path *path)
- {
-@@ -543,6 +552,7 @@
- 		return 0;
- 	return security_ops->inode_readlink(dentry);
- }
-+EXPORT_SYMBOL(security_inode_readlink);
- 
- int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
-@@ -557,6 +567,7 @@
- 		return 0;
- 	return security_ops->inode_permission(inode, mask);
- }
-+EXPORT_SYMBOL(security_inode_permission);
- 
- int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
- {
-@@ -657,6 +668,7 @@
- {
- 	return security_ops->file_permission(file, mask);
- }
-+EXPORT_SYMBOL(security_file_permission);
- 
- int security_file_alloc(struct file *file)
- {
-@@ -684,6 +696,7 @@
- 		return ret;
- 	return ima_file_mmap(file, prot);
- }
-+EXPORT_SYMBOL(security_file_mmap);
- 
- int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
- 			    unsigned long prot)
diff --git a/pkgs/core/kernel/patches/grsecurity-2.2.0-2.6.34.1-201007070910.patch \
b/pkgs/core/kernel/patches/grsecurity-2.2.0-2.6.34.1-201007070910.patch deleted file \
mode 100644 index f7c5324..0000000
--- a/pkgs/core/kernel/patches/grsecurity-2.2.0-2.6.34.1-201007070910.patch
+++ /dev/null
@@ -1,54708 +0,0 @@
-diff -urNp linux-2.6.34.1/Documentation/dontdiff \
                linux-2.6.34.1/Documentation/dontdiff
---- linux-2.6.34.1/Documentation/dontdiff	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/Documentation/dontdiff	2010-07-07 09:04:49.000000000 -0400
-@@ -3,6 +3,7 @@
- *.bin
- *.cpio
- *.csp
-+*.dbg
- *.dsp
- *.dvi
- *.elf
-@@ -40,6 +41,7 @@
- *.ver
- *.xml
- *_MODULES
-+*_reg_safe.h
- *_vga16.c
- *~
- *.9
-@@ -49,11 +51,16 @@
- 53c700_d.h
- CVS
- ChangeSet
-+GPATH
-+GRTAGS
-+GSYMS
-+GTAGS
- Image
- Kerntypes
- Module.markers
- Module.symvers
- PENDING
-+PERF*
- SCCS
- System.map*
- TAGS
-@@ -76,7 +83,10 @@ btfixupprep
- build
- bvmlinux
- bzImage*
-+capflags.c
- classlist.h*
-+clut_vga16.c
-+common-cmds.h
- comp*.log
- compile.h*
- conf
-@@ -106,13 +116,15 @@ generated
- genheaders
- genksyms
- *_gray256.c
-+hash
- ihex2fw
- ikconfig.h*
-+inat-tables.c
- initramfs_data.cpio
-+initramfs_data.cpio.bz2
- initramfs_data.cpio.gz
- initramfs_list
- kallsyms
--kconfig
- keywords.c
- ksym.c*
- ksym.h*
-@@ -136,10 +148,13 @@ mkboot
- mkbugboot
- mkcpustr
- mkdep
-+mkpiggy
- mkprep
-+mkregtable
- mktables
- mktree
- modpost
-+modules.builtin
- modules.order
- modversions.h*
- ncscope.*
-@@ -152,6 +167,7 @@ patches*
- pca200e.bin
- pca200e_ecd.bin2
- piggy.gz
-+piggy.S
- piggyback
- pnmtologo
- ppc_defs.h*
-@@ -166,6 +182,7 @@ setup
- setup.bin
- setup.elf
- sImage
-+slabinfo
- sm_tbl*
- split-include
- syscalltab.h
-@@ -189,14 +206,20 @@ version.h*
- vmlinux
- vmlinux-*
- vmlinux.aout
-+vmlinux.bin.all
-+vmlinux.bin.bz2
- vmlinux.lds
-+vmlinux.relocs
-+voffset.h
- vsyscall.lds
- vsyscall_32.lds
- wanxlfw.inc
- uImage
- unifdef
-+utsrelease.h
- wakeup.bin
- wakeup.elf
- wakeup.lds
- zImage*
- zconf.hash.c
-+zoffset.h
-diff -urNp linux-2.6.34.1/Documentation/filesystems/sysfs.txt \
                linux-2.6.34.1/Documentation/filesystems/sysfs.txt
---- linux-2.6.34.1/Documentation/filesystems/sysfs.txt	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/Documentation/filesystems/sysfs.txt	2010-07-07 09:04:50.000000000 \
                -0400
-@@ -123,8 +123,8 @@ set of sysfs operations for forwarding r
- show and store methods of the attribute owners. 
- 
- struct sysfs_ops {
--        ssize_t (*show)(struct kobject *, struct attribute *, char *);
--        ssize_t (*store)(struct kobject *, struct attribute *, const char *);
-+        ssize_t (* const show)(struct kobject *, struct attribute *, char *);
-+        ssize_t (* const store)(struct kobject *, struct attribute *, const char \
                *);
- };
- 
- [ Subsystems should have already defined a struct kobj_type as a
-diff -urNp linux-2.6.34.1/Documentation/kernel-parameters.txt \
                linux-2.6.34.1/Documentation/kernel-parameters.txt
---- linux-2.6.34.1/Documentation/kernel-parameters.txt	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/Documentation/kernel-parameters.txt	2010-07-07 09:04:50.000000000 \
                -0400
-@@ -1875,6 +1875,12 @@ and is between 256 and 4096 characters. 
- 			the specified number of seconds.  This is to be used if
- 			your oopses keep scrolling off the screen.
- 
-+	pax_nouderef	[X86-32] disables UDEREF.  Most likely needed under certain
-+			virtualization environments that don't cope well with the
-+			expand down segment used by UDEREF on X86-32.
-+
-+	pax_softmode=	[X86-32] 0/1 to disable/enable PaX softmode on boot already.
-+
- 	pcbit=		[HW,ISDN]
- 
- 	pcd.		[PARIDE]
-diff -urNp linux-2.6.34.1/Makefile linux-2.6.34.1/Makefile
---- linux-2.6.34.1/Makefile	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/Makefile	2010-07-07 09:04:57.000000000 -0400
-@@ -227,8 +227,8 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH"
- 
- HOSTCC       = gcc
- HOSTCXX      = g++
--HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 \
                -fomit-frame-pointer
--HOSTCXXFLAGS = -O2
-+HOSTCFLAGS   = -Wall -W -Wmissing-prototypes -Wstrict-prototypes -O2 \
                -fomit-frame-pointer -fno-delete-null-pointer-checks
-+HOSTCXXFLAGS = -O2 -fno-delete-null-pointer-checks
- 
- # Decide whether to build built-in, modular, or both.
- # Normally, just do built-in.
-@@ -650,7 +650,7 @@ export mod_strip_cmd
- 
- 
- ifeq ($(KBUILD_EXTMOD),)
--core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
-+core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
- 
- vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
- 		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
-diff -urNp linux-2.6.34.1/arch/alpha/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/alpha/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/alpha/include/asm/dma-mapping.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/include/asm/dma-mapping.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -3,9 +3,9 @@
- 
- #include <linux/dma-attrs.h>
- 
--extern struct dma_map_ops *dma_ops;
-+extern const struct dma_map_ops *dma_ops;
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- 	return dma_ops;
- }
-diff -urNp linux-2.6.34.1/arch/alpha/include/asm/elf.h \
                linux-2.6.34.1/arch/alpha/include/asm/elf.h
---- linux-2.6.34.1/arch/alpha/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -90,6 +90,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
- 
- #define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x1000000)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(current->personality & ADDR_LIMIT_32BIT ? 0x10000 : \
                0x120000000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(current->personality & ADDR_LIMIT_32BIT ? 14 : 28)
-+#define PAX_DELTA_STACK_LEN	(current->personality & ADDR_LIMIT_32BIT ? 14 : 19)
-+#endif
-+
- /* $0 is set by ld.so to a pointer to a function which might be 
-    registered using atexit.  This provides a mean for the dynamic
-    linker to call DT_FINI functions for shared libraries that have
-diff -urNp linux-2.6.34.1/arch/alpha/include/asm/pgtable.h \
                linux-2.6.34.1/arch/alpha/include/asm/pgtable.h
---- linux-2.6.34.1/arch/alpha/include/asm/pgtable.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/alpha/include/asm/pgtable.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -101,6 +101,17 @@ struct vm_area_struct;
- #define PAGE_SHARED	__pgprot(_PAGE_VALID | __ACCESS_BITS)
- #define PAGE_COPY	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
- #define PAGE_READONLY	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+# define PAGE_SHARED_NOEXEC	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
-+# define PAGE_COPY_NOEXEC	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | \
                _PAGE_FOE)
-+# define PAGE_READONLY_NOEXEC	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | \
                _PAGE_FOE)
-+#else
-+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
-+# define PAGE_COPY_NOEXEC	PAGE_COPY
-+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
-+#endif
-+
- #define PAGE_KERNEL	__pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
- 
- #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
-diff -urNp linux-2.6.34.1/arch/alpha/kernel/module.c \
                linux-2.6.34.1/arch/alpha/kernel/module.c
---- linux-2.6.34.1/arch/alpha/kernel/module.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/kernel/module.c	2010-07-07 09:04:42.000000000 -0400
-@@ -182,7 +182,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, 
- 
- 	/* The small sections were sorted to the end of the segment.
- 	   The following should definitely cover them.  */
--	gp = (u64)me->module_core + me->core_size - 0x8000;
-+	gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
- 	got = sechdrs[me->arch.gotsecindex].sh_addr;
- 
- 	for (i = 0; i < n; i++) {
-diff -urNp linux-2.6.34.1/arch/alpha/kernel/osf_sys.c \
                linux-2.6.34.1/arch/alpha/kernel/osf_sys.c
---- linux-2.6.34.1/arch/alpha/kernel/osf_sys.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/kernel/osf_sys.c	2010-07-07 09:04:42.000000000 -0400
-@@ -1206,6 +1206,10 @@ arch_get_unmapped_area(struct file *filp
- 	   merely specific addresses, but regions of memory -- perhaps
- 	   this feature should be incorporated into all ports?  */
- 
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
-+#endif
-+
- 	if (addr) {
- 		addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
- 		if (addr != (unsigned long) -ENOMEM)
-@@ -1213,8 +1217,8 @@ arch_get_unmapped_area(struct file *filp
- 	}
- 
- 	/* Next, try allocating at TASK_UNMAPPED_BASE.  */
--	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
--					 len, limit);
-+	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
-+
- 	if (addr != (unsigned long) -ENOMEM)
- 		return addr;
- 
-diff -urNp linux-2.6.34.1/arch/alpha/kernel/pci-noop.c \
                linux-2.6.34.1/arch/alpha/kernel/pci-noop.c
---- linux-2.6.34.1/arch/alpha/kernel/pci-noop.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/kernel/pci-noop.c	2010-07-07 09:04:42.000000000 -0400
-@@ -173,7 +173,7 @@ static int alpha_noop_set_mask(struct de
- 	return 0;
- }
- 
--struct dma_map_ops alpha_noop_ops = {
-+const struct dma_map_ops alpha_noop_ops = {
- 	.alloc_coherent		= alpha_noop_alloc_coherent,
- 	.free_coherent		= alpha_noop_free_coherent,
- 	.map_page		= alpha_noop_map_page,
-@@ -183,7 +183,7 @@ struct dma_map_ops alpha_noop_ops = {
- 	.set_dma_mask		= alpha_noop_set_mask,
- };
- 
--struct dma_map_ops *dma_ops = &alpha_noop_ops;
-+const struct dma_map_ops *dma_ops = &alpha_noop_ops;
- EXPORT_SYMBOL(dma_ops);
- 
- void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
-diff -urNp linux-2.6.34.1/arch/alpha/kernel/pci_iommu.c \
                linux-2.6.34.1/arch/alpha/kernel/pci_iommu.c
---- linux-2.6.34.1/arch/alpha/kernel/pci_iommu.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/kernel/pci_iommu.c	2010-07-07 09:04:42.000000000 -0400
-@@ -950,7 +950,7 @@ static int alpha_pci_set_mask(struct dev
- 	return 0;
- }
- 
--struct dma_map_ops alpha_pci_ops = {
-+const struct dma_map_ops alpha_pci_ops = {
- 	.alloc_coherent		= alpha_pci_alloc_coherent,
- 	.free_coherent		= alpha_pci_free_coherent,
- 	.map_page		= alpha_pci_map_page,
-@@ -962,5 +962,5 @@ struct dma_map_ops alpha_pci_ops = {
- 	.set_dma_mask		= alpha_pci_set_mask,
- };
- 
--struct dma_map_ops *dma_ops = &alpha_pci_ops;
-+const struct dma_map_ops *dma_ops = &alpha_pci_ops;
- EXPORT_SYMBOL(dma_ops);
-diff -urNp linux-2.6.34.1/arch/alpha/mm/fault.c linux-2.6.34.1/arch/alpha/mm/fault.c
---- linux-2.6.34.1/arch/alpha/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/alpha/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -54,6 +54,124 @@ __load_new_mm_context(struct mm_struct *
- 	__reload_thread(pcb);
- }
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+/*
-+ * PaX: decide what to do with offenders (regs->pc = fault address)
-+ *
-+ * returns 1 when task should be killed
-+ *         2 when patched PLT trampoline was detected
-+ *         3 when unpatched PLT trampoline was detected
-+ */
-+static int pax_handle_fetch_fault(struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+	int err;
-+
-+	do { /* PaX: patched PLT emulation #1 */
-+		unsigned int ldah, ldq, jmp;
-+
-+		err = get_user(ldah, (unsigned int *)regs->pc);
-+		err |= get_user(ldq, (unsigned int *)(regs->pc+4));
-+		err |= get_user(jmp, (unsigned int *)(regs->pc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
-+		    (ldq & 0xFFFF0000U) == 0xA77B0000U &&
-+		    jmp == 0x6BFB0000U)
-+		{
-+			unsigned long r27, addr;
-+			unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
-+			unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
-+
-+			addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) \
                + 0x8000UL);
-+			err = get_user(r27, (unsigned long *)addr);
-+			if (err)
-+				break;
-+
-+			regs->r27 = r27;
-+			regs->pc = r27;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: patched PLT emulation #2 */
-+		unsigned int ldah, lda, br;
-+
-+		err = get_user(ldah, (unsigned int *)regs->pc);
-+		err |= get_user(lda, (unsigned int *)(regs->pc+4));
-+		err |= get_user(br, (unsigned int *)(regs->pc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
-+		    (lda & 0xFFFF0000U) == 0xA77B0000U &&
-+		    (br & 0xFFE00000U) == 0xC3E00000U)
-+		{
-+			unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
-+			unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
-+			unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
-+
-+			regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + \
                0x8000UL);
-+			regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: unpatched PLT emulation */
-+		unsigned int br;
-+
-+		err = get_user(br, (unsigned int *)regs->pc);
-+
-+		if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
-+			unsigned int br2, ldq, nop, jmp;
-+			unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
-+
-+			addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
-+			err = get_user(br2, (unsigned int *)addr);
-+			err |= get_user(ldq, (unsigned int *)(addr+4));
-+			err |= get_user(nop, (unsigned int *)(addr+8));
-+			err |= get_user(jmp, (unsigned int *)(addr+12));
-+			err |= get_user(resolver, (unsigned long *)(addr+16));
-+
-+			if (err)
-+				break;
-+
-+			if (br2 == 0xC3600000U &&
-+			    ldq == 0xA77B000CU &&
-+			    nop == 0x47FF041FU &&
-+			    jmp == 0x6B7B0000U)
-+			{
-+				regs->r28 = regs->pc+4;
-+				regs->r27 = addr+16;
-+				regs->pc = resolver;
-+				return 3;
-+			}
-+		}
-+	} while (0);
-+#endif
-+
-+	return 1;
-+}
-+
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 5; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
- 
- /*
-  * This routine handles page faults.  It determines the address,
-@@ -131,8 +249,29 @@ do_page_fault(unsigned long address, uns
-  good_area:
- 	si_code = SEGV_ACCERR;
- 	if (cause < 0) {
--		if (!(vma->vm_flags & VM_EXEC))
-+		if (!(vma->vm_flags & VM_EXEC)) {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+			if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
-+				goto bad_area;
-+
-+			up_read(&mm->mmap_sem);
-+			switch (pax_handle_fetch_fault(regs)) {
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+			case 2:
-+			case 3:
-+				return;
-+#endif
-+
-+			}
-+			pax_report_fault(regs, (void *)regs->pc, (void *)rdusp());
-+			do_group_exit(SIGKILL);
-+#else
- 			goto bad_area;
-+#endif
-+
-+		}
- 	} else if (!cause) {
- 		/* Allow reads even for write-only mappings */
- 		if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
-diff -urNp linux-2.6.34.1/arch/arm/include/asm/elf.h \
                linux-2.6.34.1/arch/arm/include/asm/elf.h
---- linux-2.6.34.1/arch/arm/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -111,7 +111,14 @@ int dump_task_regs(struct task_struct *t
-    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	(2 * TASK_SIZE / 3)
-+#define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
-+
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	0x00008000UL
-+
-+#define PAX_DELTA_MMAP_LEN	((current->personality == PER_LINUX_32BIT) ? 16 : 10)
-+#define PAX_DELTA_STACK_LEN	((current->personality == PER_LINUX_32BIT) ? 16 : 10)
-+#endif
- 
- /* 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 -urNp linux-2.6.34.1/arch/arm/include/asm/kmap_types.h \
                linux-2.6.34.1/arch/arm/include/asm/kmap_types.h
---- linux-2.6.34.1/arch/arm/include/asm/kmap_types.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/arm/include/asm/kmap_types.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -20,6 +20,7 @@ enum km_type {
- 	KM_SOFTIRQ1,
- 	KM_L1_CACHE,
- 	KM_L2_CACHE,
-+	KM_CLEARPAGE,
- 	KM_TYPE_NR
- };
- 
-diff -urNp linux-2.6.34.1/arch/arm/include/asm/uaccess.h \
                linux-2.6.34.1/arch/arm/include/asm/uaccess.h
---- linux-2.6.34.1/arch/arm/include/asm/uaccess.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/arm/include/asm/uaccess.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -403,6 +403,9 @@ extern unsigned long __must_check __strn
- 
- static inline unsigned long __must_check copy_from_user(void *to, const void __user \
                *from, unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (access_ok(VERIFY_READ, from, n))
- 		n = __copy_from_user(to, from, n);
- 	else /* security hole - plug it */
-@@ -412,6 +415,9 @@ static inline unsigned long __must_check
- 
- static inline unsigned long __must_check copy_to_user(void __user *to, const void \
                *from, unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (access_ok(VERIFY_WRITE, to, n))
- 		n = __copy_to_user(to, from, n);
- 	return n;
-diff -urNp linux-2.6.34.1/arch/arm/kernel/kgdb.c \
                linux-2.6.34.1/arch/arm/kernel/kgdb.c
---- linux-2.6.34.1/arch/arm/kernel/kgdb.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/kernel/kgdb.c	2010-07-07 09:04:42.000000000 -0400
-@@ -203,7 +203,7 @@ void kgdb_arch_exit(void)
-  * and we handle the normal undef case within the do_undefinstr
-  * handler.
-  */
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- #ifndef __ARMEB__
- 	.gdb_bpt_instr		= {0xfe, 0xde, 0xff, 0xe7}
- #else /* ! __ARMEB__ */
-diff -urNp linux-2.6.34.1/arch/arm/mach-at91/pm.c \
                linux-2.6.34.1/arch/arm/mach-at91/pm.c
---- linux-2.6.34.1/arch/arm/mach-at91/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-at91/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -294,7 +294,7 @@ static void at91_pm_end(void)
- }
- 
- 
--static struct platform_suspend_ops at91_pm_ops ={
-+static const struct platform_suspend_ops at91_pm_ops ={
- 	.valid	= at91_pm_valid_state,
- 	.begin	= at91_pm_begin,
- 	.enter	= at91_pm_enter,
-diff -urNp linux-2.6.34.1/arch/arm/mach-davinci/pm.c \
                linux-2.6.34.1/arch/arm/mach-davinci/pm.c
---- linux-2.6.34.1/arch/arm/mach-davinci/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-davinci/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -110,7 +110,7 @@ static int davinci_pm_enter(suspend_stat
- 	return ret;
- }
- 
--static struct platform_suspend_ops davinci_pm_ops = {
-+static const struct platform_suspend_ops davinci_pm_ops = {
- 	.enter		= davinci_pm_enter,
- 	.valid		= suspend_valid_only_mem,
- };
-diff -urNp linux-2.6.34.1/arch/arm/mach-omap1/pm.c \
                linux-2.6.34.1/arch/arm/mach-omap1/pm.c
---- linux-2.6.34.1/arch/arm/mach-omap1/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-omap1/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -647,7 +647,7 @@ static struct irqaction omap_wakeup_irq 
- 
- 
- 
--static struct platform_suspend_ops omap_pm_ops ={
-+static const struct platform_suspend_ops omap_pm_ops ={
- 	.prepare	= omap_pm_prepare,
- 	.enter		= omap_pm_enter,
- 	.finish		= omap_pm_finish,
-diff -urNp linux-2.6.34.1/arch/arm/mach-omap2/pm24xx.c \
                linux-2.6.34.1/arch/arm/mach-omap2/pm24xx.c
---- linux-2.6.34.1/arch/arm/mach-omap2/pm24xx.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-omap2/pm24xx.c	2010-07-07 09:04:42.000000000 -0400
-@@ -324,7 +324,7 @@ static void omap2_pm_finish(void)
- 	enable_hlt();
- }
- 
--static struct platform_suspend_ops omap_pm_ops = {
-+static const struct platform_suspend_ops omap_pm_ops = {
- 	.prepare	= omap2_pm_prepare,
- 	.enter		= omap2_pm_enter,
- 	.finish		= omap2_pm_finish,
-diff -urNp linux-2.6.34.1/arch/arm/mach-omap2/pm34xx.c \
                linux-2.6.34.1/arch/arm/mach-omap2/pm34xx.c
---- linux-2.6.34.1/arch/arm/mach-omap2/pm34xx.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-omap2/pm34xx.c	2010-07-07 09:04:42.000000000 -0400
-@@ -651,7 +651,7 @@ static void omap3_pm_end(void)
- 	return;
- }
- 
--static struct platform_suspend_ops omap_pm_ops = {
-+static const struct platform_suspend_ops omap_pm_ops = {
- 	.begin		= omap3_pm_begin,
- 	.end		= omap3_pm_end,
- 	.prepare	= omap3_pm_prepare,
-diff -urNp linux-2.6.34.1/arch/arm/mach-pnx4008/pm.c \
                linux-2.6.34.1/arch/arm/mach-pnx4008/pm.c
---- linux-2.6.34.1/arch/arm/mach-pnx4008/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-pnx4008/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -119,7 +119,7 @@ static int pnx4008_pm_valid(suspend_stat
- 	       (state == PM_SUSPEND_MEM);
- }
- 
--static struct platform_suspend_ops pnx4008_pm_ops = {
-+static const struct platform_suspend_ops pnx4008_pm_ops = {
- 	.enter = pnx4008_pm_enter,
- 	.valid = pnx4008_pm_valid,
- };
-diff -urNp linux-2.6.34.1/arch/arm/mach-pxa/pm.c \
                linux-2.6.34.1/arch/arm/mach-pxa/pm.c
---- linux-2.6.34.1/arch/arm/mach-pxa/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-pxa/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -96,7 +96,7 @@ void pxa_pm_finish(void)
- 		pxa_cpu_pm_fns->finish();
- }
- 
--static struct platform_suspend_ops pxa_pm_ops = {
-+static const struct platform_suspend_ops pxa_pm_ops = {
- 	.valid		= pxa_pm_valid,
- 	.enter		= pxa_pm_enter,
- 	.prepare	= pxa_pm_prepare,
-diff -urNp linux-2.6.34.1/arch/arm/mach-pxa/sharpsl_pm.c \
                linux-2.6.34.1/arch/arm/mach-pxa/sharpsl_pm.c
---- linux-2.6.34.1/arch/arm/mach-pxa/sharpsl_pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/arm/mach-pxa/sharpsl_pm.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -892,7 +892,7 @@ static void sharpsl_apm_get_power_status
- }
- 
- #ifdef CONFIG_PM
--static struct platform_suspend_ops sharpsl_pm_ops = {
-+static const struct platform_suspend_ops sharpsl_pm_ops = {
- 	.prepare	= pxa_pm_prepare,
- 	.finish		= pxa_pm_finish,
- 	.enter		= corgi_pxa_pm_enter,
-diff -urNp linux-2.6.34.1/arch/arm/mach-sa1100/pm.c \
                linux-2.6.34.1/arch/arm/mach-sa1100/pm.c
---- linux-2.6.34.1/arch/arm/mach-sa1100/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mach-sa1100/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -120,7 +120,7 @@ unsigned long sleep_phys_sp(void *sp)
- 	return virt_to_phys(sp);
- }
- 
--static struct platform_suspend_ops sa11x0_pm_ops = {
-+static const struct platform_suspend_ops sa11x0_pm_ops = {
- 	.enter		= sa11x0_pm_enter,
- 	.valid		= suspend_valid_only_mem,
- };
-diff -urNp linux-2.6.34.1/arch/arm/mm/fault.c linux-2.6.34.1/arch/arm/mm/fault.c
---- linux-2.6.34.1/arch/arm/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -167,6 +167,13 @@ __do_user_fault(struct task_struct *tsk,
- 	}
- #endif
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+	if (fsr & FSR_LNX_PF) {
-+		pax_report_fault(regs, (void *)regs->ARM_pc, (void *)regs->ARM_sp);
-+		do_group_exit(SIGKILL);
-+	}
-+#endif
-+
- 	tsk->thread.address = addr;
- 	tsk->thread.error_code = fsr;
- 	tsk->thread.trap_no = 14;
-@@ -364,6 +371,33 @@ do_page_fault(unsigned long addr, unsign
- }
- #endif					/* CONFIG_MMU */
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 20; i++) {
-+		unsigned char c;
-+		if (get_user(c, (__force unsigned char __user *)pc+i))
-+			printk(KERN_CONT "?? ");
-+		else
-+			printk(KERN_CONT "%02x ", c);
-+	}
-+	printk("\n");
-+
-+	printk(KERN_ERR "PAX: bytes at SP-4: ");
-+	for (i = -1; i < 20; i++) {
-+		unsigned long c;
-+		if (get_user(c, (__force unsigned long __user *)sp+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08lx ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- /*
-  * First Level Translation Fault Handler
-  *
-diff -urNp linux-2.6.34.1/arch/arm/mm/mmap.c linux-2.6.34.1/arch/arm/mm/mmap.c
---- linux-2.6.34.1/arch/arm/mm/mmap.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/mm/mmap.c	2010-07-07 09:04:42.000000000 -0400
-@@ -63,6 +63,10 @@ arch_get_unmapped_area(struct file *filp
- 	if (len > TASK_SIZE)
- 		return -ENOMEM;
- 
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (!(mm->pax_flags & MF_PAX_RANDMMAP))
-+#endif
-+
- 	if (addr) {
- 		if (do_align)
- 			addr = COLOUR_ALIGN(addr, pgoff);
-@@ -75,10 +79,10 @@ arch_get_unmapped_area(struct file *filp
- 			return addr;
- 	}
- 	if (len > mm->cached_hole_size) {
--	        start_addr = addr = mm->free_area_cache;
-+		start_addr = addr = mm->free_area_cache;
- 	} else {
--	        start_addr = addr = TASK_UNMAPPED_BASE;
--	        mm->cached_hole_size = 0;
-+		start_addr = addr = mm->mmap_base;
-+		mm->cached_hole_size = 0;
- 	}
- 
- full_search:
-@@ -94,8 +98,8 @@ full_search:
- 			 * Start a new search - just in case we missed
- 			 * some holes.
- 			 */
--			if (start_addr != TASK_UNMAPPED_BASE) {
--				start_addr = addr = TASK_UNMAPPED_BASE;
-+			if (start_addr != mm->mmap_base) {
-+				start_addr = addr = mm->mmap_base;
- 				mm->cached_hole_size = 0;
- 				goto full_search;
- 			}
-diff -urNp linux-2.6.34.1/arch/arm/plat-samsung/pm.c \
                linux-2.6.34.1/arch/arm/plat-samsung/pm.c
---- linux-2.6.34.1/arch/arm/plat-samsung/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/arm/plat-samsung/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -355,7 +355,7 @@ static void s3c_pm_finish(void)
- 	s3c_pm_check_cleanup();
- }
- 
--static struct platform_suspend_ops s3c_pm_ops = {
-+static const struct platform_suspend_ops s3c_pm_ops = {
- 	.enter		= s3c_pm_enter,
- 	.prepare	= s3c_pm_prepare,
- 	.finish		= s3c_pm_finish,
-diff -urNp linux-2.6.34.1/arch/avr32/include/asm/elf.h \
                linux-2.6.34.1/arch/avr32/include/asm/elf.h
---- linux-2.6.34.1/arch/avr32/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/avr32/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -84,8 +84,14 @@ typedef struct user_fpu_struct elf_fpreg
-    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         (2 * TASK_SIZE / 3)
-+#define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	0x00001000UL
-+
-+#define PAX_DELTA_MMAP_LEN	15
-+#define PAX_DELTA_STACK_LEN	15
-+#endif
- 
- /* 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 -urNp linux-2.6.34.1/arch/avr32/include/asm/kmap_types.h \
                linux-2.6.34.1/arch/avr32/include/asm/kmap_types.h
---- linux-2.6.34.1/arch/avr32/include/asm/kmap_types.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/avr32/include/asm/kmap_types.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -22,7 +22,8 @@ D(10)	KM_IRQ0,
- D(11)	KM_IRQ1,
- D(12)	KM_SOFTIRQ0,
- D(13)	KM_SOFTIRQ1,
--D(14)	KM_TYPE_NR
-+D(14)	KM_CLEARPAGE,
-+D(15)	KM_TYPE_NR
- };
- 
- #undef D
-diff -urNp linux-2.6.34.1/arch/avr32/mach-at32ap/pm.c \
                linux-2.6.34.1/arch/avr32/mach-at32ap/pm.c
---- linux-2.6.34.1/arch/avr32/mach-at32ap/pm.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/avr32/mach-at32ap/pm.c	2010-07-07 09:04:42.000000000 -0400
-@@ -176,7 +176,7 @@ out:
- 	return 0;
- }
- 
--static struct platform_suspend_ops avr32_pm_ops = {
-+static const struct platform_suspend_ops avr32_pm_ops = {
- 	.valid	= avr32_pm_valid_state,
- 	.enter	= avr32_pm_enter,
- };
-diff -urNp linux-2.6.34.1/arch/avr32/mm/fault.c linux-2.6.34.1/arch/avr32/mm/fault.c
---- linux-2.6.34.1/arch/avr32/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/avr32/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -41,6 +41,23 @@ static inline int notify_page_fault(stru
- 
- int exception_trace = 1;
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 20; i++) {
-+		unsigned char c;
-+		if (get_user(c, (unsigned char *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%02x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- /*
-  * This routine handles page faults. It determines the address and the
-  * problem, and then passes it off to one of the appropriate routines.
-@@ -157,6 +174,16 @@ bad_area:
- 	up_read(&mm->mmap_sem);
- 
- 	if (user_mode(regs)) {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if (mm->pax_flags & MF_PAX_PAGEEXEC) {
-+			if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) {
-+				pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp);
-+				do_group_exit(SIGKILL);
-+			}
-+		}
-+#endif
-+
- 		if (exception_trace && printk_ratelimit())
- 			printk("%s%s[%d]: segfault at %08lx pc %08lx "
- 			       "sp %08lx ecr %lu\n",
-diff -urNp linux-2.6.34.1/arch/blackfin/kernel/kgdb.c \
                linux-2.6.34.1/arch/blackfin/kernel/kgdb.c
---- linux-2.6.34.1/arch/blackfin/kernel/kgdb.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/blackfin/kernel/kgdb.c	2010-07-07 09:04:42.000000000 -0400
-@@ -397,7 +397,7 @@ int kgdb_arch_handle_exception(int vecto
- 	return -1;		/* this means that we do not want to exit from the handler */
- }
- 
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- 	.gdb_bpt_instr = {0xa1},
- #ifdef CONFIG_SMP
- 	.flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
-diff -urNp linux-2.6.34.1/arch/blackfin/mach-common/pm.c \
                linux-2.6.34.1/arch/blackfin/mach-common/pm.c
---- linux-2.6.34.1/arch/blackfin/mach-common/pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/blackfin/mach-common/pm.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -256,7 +256,7 @@ static int bfin_pm_enter(suspend_state_t
- 	return 0;
- }
- 
--struct platform_suspend_ops bfin_pm_ops = {
-+const struct platform_suspend_ops bfin_pm_ops = {
- 	.enter = bfin_pm_enter,
- 	.valid	= bfin_pm_valid,
- };
-diff -urNp linux-2.6.34.1/arch/blackfin/mm/maccess.c \
                linux-2.6.34.1/arch/blackfin/mm/maccess.c
---- linux-2.6.34.1/arch/blackfin/mm/maccess.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/blackfin/mm/maccess.c	2010-07-07 09:04:42.000000000 -0400
-@@ -16,7 +16,7 @@ static int validate_memory_access_addres
- 	return bfin_mem_access_type(addr, size);
- }
- 
--long probe_kernel_read(void *dst, void *src, size_t size)
-+long probe_kernel_read(void *dst, const void *src, size_t size)
- {
- 	unsigned long lsrc = (unsigned long)src;
- 	int mem_type;
-@@ -55,7 +55,7 @@ long probe_kernel_read(void *dst, void *
- 	return -EFAULT;
- }
- 
--long probe_kernel_write(void *dst, void *src, size_t size)
-+long probe_kernel_write(void *dst, const void *src, size_t size)
- {
- 	unsigned long ldst = (unsigned long)dst;
- 	int mem_type;
-diff -urNp linux-2.6.34.1/arch/frv/include/asm/kmap_types.h \
                linux-2.6.34.1/arch/frv/include/asm/kmap_types.h
---- linux-2.6.34.1/arch/frv/include/asm/kmap_types.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/frv/include/asm/kmap_types.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -23,6 +23,7 @@ enum km_type {
- 	KM_IRQ1,
- 	KM_SOFTIRQ0,
- 	KM_SOFTIRQ1,
-+	KM_CLEARPAGE,
- 	KM_TYPE_NR
- };
- 
-diff -urNp linux-2.6.34.1/arch/ia64/hp/common/hwsw_iommu.c \
                linux-2.6.34.1/arch/ia64/hp/common/hwsw_iommu.c
---- linux-2.6.34.1/arch/ia64/hp/common/hwsw_iommu.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/hp/common/hwsw_iommu.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -17,7 +17,7 @@
- #include <linux/swiotlb.h>
- #include <asm/machvec.h>
- 
--extern struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
-+extern const struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
- 
- /* swiotlb declarations & definitions: */
- extern int swiotlb_late_init_with_default_size (size_t size);
-@@ -33,7 +33,7 @@ static inline int use_swiotlb(struct dev
- 		!sba_dma_ops.dma_supported(dev, *dev->dma_mask);
- }
- 
--struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
-+const struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
- {
- 	if (use_swiotlb(dev))
- 		return &swiotlb_dma_ops;
-diff -urNp linux-2.6.34.1/arch/ia64/hp/common/sba_iommu.c \
                linux-2.6.34.1/arch/ia64/hp/common/sba_iommu.c
---- linux-2.6.34.1/arch/ia64/hp/common/sba_iommu.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/hp/common/sba_iommu.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -2097,7 +2097,7 @@ static struct acpi_driver acpi_sba_ioc_d
- 	},
- };
- 
--extern struct dma_map_ops swiotlb_dma_ops;
-+extern const struct dma_map_ops swiotlb_dma_ops;
- 
- static int __init
- sba_init(void)
-@@ -2211,7 +2211,7 @@ sba_page_override(char *str)
- 
- __setup("sbapagesize=",sba_page_override);
- 
--struct dma_map_ops sba_dma_ops = {
-+const struct dma_map_ops sba_dma_ops = {
- 	.alloc_coherent		= sba_alloc_coherent,
- 	.free_coherent		= sba_free_coherent,
- 	.map_page		= sba_map_page,
-diff -urNp linux-2.6.34.1/arch/ia64/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/ia64/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/ia64/include/asm/dma-mapping.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/include/asm/dma-mapping.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -12,7 +12,7 @@
- 
- #define ARCH_HAS_DMA_GET_REQUIRED_MASK
- 
--extern struct dma_map_ops *dma_ops;
-+extern const struct dma_map_ops *dma_ops;
- extern struct ia64_machine_vector ia64_mv;
- extern void set_iommu_machvec(void);
- 
-@@ -24,7 +24,7 @@ extern void machvec_dma_sync_sg(struct d
- static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- 				       dma_addr_t *daddr, gfp_t gfp)
- {
--	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-+	const struct dma_map_ops *ops = platform_dma_get_ops(dev);
- 	void *caddr;
- 
- 	caddr = ops->alloc_coherent(dev, size, daddr, gfp);
-@@ -35,7 +35,7 @@ static inline void *dma_alloc_coherent(s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *caddr, dma_addr_t daddr)
- {
--	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-+	const struct dma_map_ops *ops = platform_dma_get_ops(dev);
- 	debug_dma_free_coherent(dev, size, caddr, daddr);
- 	ops->free_coherent(dev, size, caddr, daddr);
- }
-@@ -49,13 +49,13 @@ static inline void dma_free_coherent(str
- 
- static inline int dma_mapping_error(struct device *dev, dma_addr_t daddr)
- {
--	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-+	const struct dma_map_ops *ops = platform_dma_get_ops(dev);
- 	return ops->mapping_error(dev, daddr);
- }
- 
- static inline int dma_supported(struct device *dev, u64 mask)
- {
--	struct dma_map_ops *ops = platform_dma_get_ops(dev);
-+	const struct dma_map_ops *ops = platform_dma_get_ops(dev);
- 	return ops->dma_supported(dev, mask);
- }
- 
-diff -urNp linux-2.6.34.1/arch/ia64/include/asm/elf.h \
                linux-2.6.34.1/arch/ia64/include/asm/elf.h
---- linux-2.6.34.1/arch/ia64/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -42,6 +42,13 @@
-  */
- #define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x800000000UL)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(current->personality == PER_LINUX32 ? 0x08048000UL : \
                0x4000000000000000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT \
                - 13)
-+#define PAX_DELTA_STACK_LEN	(current->personality == PER_LINUX32 ? 16 : \
                3*PAGE_SHIFT - 13)
-+#endif
-+
- #define PT_IA_64_UNWIND		0x70000001
- 
- /* IA-64 relocations: */
-diff -urNp linux-2.6.34.1/arch/ia64/include/asm/machvec.h \
                linux-2.6.34.1/arch/ia64/include/asm/machvec.h
---- linux-2.6.34.1/arch/ia64/include/asm/machvec.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/include/asm/machvec.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -45,7 +45,7 @@ typedef void ia64_mv_kernel_launch_event
- /* DMA-mapping interface: */
- typedef void ia64_mv_dma_init (void);
- typedef u64 ia64_mv_dma_get_required_mask (struct device *);
--typedef struct dma_map_ops *ia64_mv_dma_get_ops(struct device *);
-+typedef const struct dma_map_ops *ia64_mv_dma_get_ops(struct device *);
- 
- /*
-  * WARNING: The legacy I/O space is _architected_.  Platforms are
-@@ -251,7 +251,7 @@ extern void machvec_init_from_cmdline(co
- # endif /* CONFIG_IA64_GENERIC */
- 
- extern void swiotlb_dma_init(void);
--extern struct dma_map_ops *dma_get_ops(struct device *);
-+extern const struct dma_map_ops *dma_get_ops(struct device *);
- 
- /*
-  * Define default versions so we can extend machvec for new platforms without \
                having
-diff -urNp linux-2.6.34.1/arch/ia64/include/asm/pgtable.h \
                linux-2.6.34.1/arch/ia64/include/asm/pgtable.h
---- linux-2.6.34.1/arch/ia64/include/asm/pgtable.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/include/asm/pgtable.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -143,6 +143,17 @@
- #define PAGE_READONLY	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
- #define PAGE_COPY	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
- #define PAGE_COPY_EXEC	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+# define PAGE_SHARED_NOEXEC	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
-+# define PAGE_READONLY_NOEXEC	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
-+# define PAGE_COPY_NOEXEC	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
-+#else
-+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
-+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
-+# define PAGE_COPY_NOEXEC	PAGE_COPY
-+#endif
-+
- #define PAGE_GATE	__pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
- #define PAGE_KERNEL	__pgprot(__DIRTY_BITS  | _PAGE_PL_0 | _PAGE_AR_RWX)
- #define PAGE_KERNELRX	__pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
-diff -urNp linux-2.6.34.1/arch/ia64/include/asm/uaccess.h \
                linux-2.6.34.1/arch/ia64/include/asm/uaccess.h
---- linux-2.6.34.1/arch/ia64/include/asm/uaccess.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/include/asm/uaccess.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -257,7 +257,7 @@ __copy_from_user (void *to, const void _
- 	const void *__cu_from = (from);							\
- 	long __cu_len = (n);								\
- 											\
--	if (__access_ok(__cu_to, __cu_len, get_fs()))					\
-+	if (__cu_len > 0  && __cu_len <= INT_MAX && __access_ok(__cu_to, __cu_len, \
                get_fs()))			\
- 		__cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len);	\
- 	__cu_len;									\
- })
-@@ -269,7 +269,7 @@ __copy_from_user (void *to, const void _
- 	long __cu_len = (n);								\
- 											\
- 	__chk_user_ptr(__cu_from);							\
--	if (__access_ok(__cu_from, __cu_len, get_fs()))					\
-+	if (__cu_len > 0 && __cu_len <= INT_MAX  && __access_ok(__cu_from, __cu_len, \
                get_fs()))			\
- 		__cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len);	\
- 	__cu_len;									\
- })
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/dma-mapping.c \
                linux-2.6.34.1/arch/ia64/kernel/dma-mapping.c
---- linux-2.6.34.1/arch/ia64/kernel/dma-mapping.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/dma-mapping.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -3,7 +3,7 @@
- /* Set this to 1 if there is a HW IOMMU in the system */
- int iommu_detected __read_mostly;
- 
--struct dma_map_ops *dma_ops;
-+const struct dma_map_ops *dma_ops;
- EXPORT_SYMBOL(dma_ops);
- 
- #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
-@@ -16,7 +16,7 @@ static int __init dma_init(void)
- }
- fs_initcall(dma_init);
- 
--struct dma_map_ops *dma_get_ops(struct device *dev)
-+const struct dma_map_ops *dma_get_ops(struct device *dev)
- {
- 	return dma_ops;
- }
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/module.c \
                linux-2.6.34.1/arch/ia64/kernel/module.c
---- linux-2.6.34.1/arch/ia64/kernel/module.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/module.c	2010-07-07 09:04:42.000000000 -0400
-@@ -315,8 +315,7 @@ module_alloc (unsigned long size)
- void
- module_free (struct module *mod, void *module_region)
- {
--	if (mod && mod->arch.init_unw_table &&
--	    module_region == mod->module_init) {
-+	if (mod && mod->arch.init_unw_table && module_region == mod->module_init_rx) {
- 		unw_remove_unwind_table(mod->arch.init_unw_table);
- 		mod->arch.init_unw_table = NULL;
- 	}
-@@ -502,15 +501,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
- }
- 
- static inline int
-+in_init_rx (const struct module *mod, uint64_t addr)
-+{
-+	return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
-+}
-+
-+static inline int
-+in_init_rw (const struct module *mod, uint64_t addr)
-+{
-+	return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
-+}
-+
-+static inline int
- in_init (const struct module *mod, uint64_t addr)
- {
--	return addr - (uint64_t) mod->module_init < mod->init_size;
-+	return in_init_rx(mod, addr) || in_init_rw(mod, addr);
-+}
-+
-+static inline int
-+in_core_rx (const struct module *mod, uint64_t addr)
-+{
-+	return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
-+}
-+
-+static inline int
-+in_core_rw (const struct module *mod, uint64_t addr)
-+{
-+	return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
- }
- 
- static inline int
- in_core (const struct module *mod, uint64_t addr)
- {
--	return addr - (uint64_t) mod->module_core < mod->core_size;
-+	return in_core_rx(mod, addr) || in_core_rw(mod, addr);
- }
- 
- static inline int
-@@ -693,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
- 		break;
- 
- 	      case RV_BDREL:
--		val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core);
-+		if (in_init_rx(mod, val))
-+			val -= (uint64_t) mod->module_init_rx;
-+		else if (in_init_rw(mod, val))
-+			val -= (uint64_t) mod->module_init_rw;
-+		else if (in_core_rx(mod, val))
-+			val -= (uint64_t) mod->module_core_rx;
-+		else if (in_core_rw(mod, val))
-+			val -= (uint64_t) mod->module_core_rw;
- 		break;
- 
- 	      case RV_LTV:
-@@ -828,15 +858,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
- 		 *     addresses have been selected...
- 		 */
- 		uint64_t gp;
--		if (mod->core_size > MAX_LTOFF)
-+		if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
- 			/*
- 			 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
- 			 * at the end of the module.
- 			 */
--			gp = mod->core_size - MAX_LTOFF / 2;
-+			gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
- 		else
--			gp = mod->core_size / 2;
--		gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
-+			gp = (mod->core_size_rx + mod->core_size_rw) / 2;
-+		gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8);
- 		mod->arch.gp = gp;
- 		DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp);
- 	}
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/pci-dma.c \
                linux-2.6.34.1/arch/ia64/kernel/pci-dma.c
---- linux-2.6.34.1/arch/ia64/kernel/pci-dma.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/pci-dma.c	2010-07-07 09:04:42.000000000 -0400
-@@ -43,7 +43,7 @@ struct device fallback_dev = {
- 	.dma_mask = &fallback_dev.coherent_dma_mask,
- };
- 
--extern struct dma_map_ops intel_dma_ops;
-+extern const struct dma_map_ops intel_dma_ops;
- 
- static int __init pci_iommu_init(void)
- {
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/pci-swiotlb.c \
                linux-2.6.34.1/arch/ia64/kernel/pci-swiotlb.c
---- linux-2.6.34.1/arch/ia64/kernel/pci-swiotlb.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/pci-swiotlb.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -22,7 +22,7 @@ static void *ia64_swiotlb_alloc_coherent
- 	return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
- }
- 
--struct dma_map_ops swiotlb_dma_ops = {
-+const struct dma_map_ops swiotlb_dma_ops = {
- 	.alloc_coherent = ia64_swiotlb_alloc_coherent,
- 	.free_coherent = swiotlb_free_coherent,
- 	.map_page = swiotlb_map_page,
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/sys_ia64.c \
                linux-2.6.34.1/arch/ia64/kernel/sys_ia64.c
---- linux-2.6.34.1/arch/ia64/kernel/sys_ia64.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/sys_ia64.c	2010-07-07 09:04:42.000000000 -0400
-@@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil
- 	if (REGION_NUMBER(addr) == RGN_HPAGE)
- 		addr = 0;
- #endif
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (mm->pax_flags & MF_PAX_RANDMMAP)
-+		addr = mm->free_area_cache;
-+	else
-+#endif
-+
- 	if (!addr)
- 		addr = mm->free_area_cache;
- 
-@@ -61,9 +68,9 @@ arch_get_unmapped_area (struct file *fil
- 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
- 		/* At this point:  (!vma || addr < vma->vm_end). */
- 		if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
--			if (start_addr != TASK_UNMAPPED_BASE) {
-+			if (start_addr != mm->mmap_base) {
- 				/* Start a new search --- just in case we missed some holes.  */
--				addr = TASK_UNMAPPED_BASE;
-+				addr = mm->mmap_base;
- 				goto full_search;
- 			}
- 			return -ENOMEM;
-diff -urNp linux-2.6.34.1/arch/ia64/kernel/vmlinux.lds.S \
                linux-2.6.34.1/arch/ia64/kernel/vmlinux.lds.S
---- linux-2.6.34.1/arch/ia64/kernel/vmlinux.lds.S	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/ia64/kernel/vmlinux.lds.S	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -196,7 +196,7 @@ SECTIONS
-   /* Per-cpu data: */
-   . = ALIGN(PERCPU_PAGE_SIZE);
-   PERCPU_VADDR(PERCPU_ADDR, :percpu)
--  __phys_per_cpu_start = __per_cpu_load;
-+  __phys_per_cpu_start = per_cpu_load;
-   . = __phys_per_cpu_start + PERCPU_PAGE_SIZE;	/* ensure percpu data fits
-   						 * into percpu page size
- 						 */
-diff -urNp linux-2.6.34.1/arch/ia64/mm/fault.c linux-2.6.34.1/arch/ia64/mm/fault.c
---- linux-2.6.34.1/arch/ia64/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned 
- 	return pte_present(pte);
- }
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 8; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- void __kprobes
- ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
- {
-@@ -145,9 +162,23 @@ ia64_do_page_fault (unsigned long addres
- 	mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
- 		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
- 
--	if ((vma->vm_flags & mask) != mask)
-+	if ((vma->vm_flags & mask) != mask) {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
-+			if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip)
-+				goto bad_area;
-+
-+			up_read(&mm->mmap_sem);
-+			pax_report_fault(regs, (void *)regs->cr_iip, (void *)regs->r12);
-+			do_group_exit(SIGKILL);
-+		}
-+#endif
-+
- 		goto bad_area;
- 
-+	}
-+
-   survive:
- 	/*
- 	 * If for any reason at all we couldn't handle the fault, make
-diff -urNp linux-2.6.34.1/arch/ia64/mm/init.c linux-2.6.34.1/arch/ia64/mm/init.c
---- linux-2.6.34.1/arch/ia64/mm/init.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/mm/init.c	2010-07-07 09:04:42.000000000 -0400
-@@ -122,6 +122,19 @@ ia64_init_addr_space (void)
- 		vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
- 		vma->vm_end = vma->vm_start + PAGE_SIZE;
- 		vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT;
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if (current->mm->pax_flags & MF_PAX_PAGEEXEC) {
-+			vma->vm_flags &= ~VM_EXEC;
-+
-+#ifdef CONFIG_PAX_MPROTECT
-+			if (current->mm->pax_flags & MF_PAX_MPROTECT)
-+				vma->vm_flags &= ~VM_MAYEXEC;
-+#endif
-+
-+		}
-+#endif
-+
- 		vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- 		down_write(&current->mm->mmap_sem);
- 		if (insert_vm_struct(current->mm, vma)) {
-diff -urNp linux-2.6.34.1/arch/ia64/sn/pci/pci_dma.c \
                linux-2.6.34.1/arch/ia64/sn/pci/pci_dma.c
---- linux-2.6.34.1/arch/ia64/sn/pci/pci_dma.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/ia64/sn/pci/pci_dma.c	2010-07-07 09:04:42.000000000 -0400
-@@ -465,7 +465,7 @@ int sn_pci_legacy_write(struct pci_bus *
- 	return ret;
- }
- 
--static struct dma_map_ops sn_dma_ops = {
-+static const struct dma_map_ops sn_dma_ops = {
- 	.alloc_coherent		= sn_dma_alloc_coherent,
- 	.free_coherent		= sn_dma_free_coherent,
- 	.map_page		= sn_dma_map_page,
-diff -urNp linux-2.6.34.1/arch/m32r/lib/usercopy.c \
                linux-2.6.34.1/arch/m32r/lib/usercopy.c
---- linux-2.6.34.1/arch/m32r/lib/usercopy.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/m32r/lib/usercopy.c	2010-07-07 09:04:42.000000000 -0400
-@@ -14,6 +14,9 @@
- unsigned long
- __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	prefetch(from);
- 	if (access_ok(VERIFY_WRITE, to, n))
- 		__copy_user(to,from,n);
-@@ -23,6 +26,9 @@ __generic_copy_to_user(void __user *to, 
- unsigned long
- __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	prefetchw(to);
- 	if (access_ok(VERIFY_READ, from, n))
- 		__copy_user_zeroing(to,from,n);
-diff -urNp linux-2.6.34.1/arch/microblaze/include/asm/device.h \
                linux-2.6.34.1/arch/microblaze/include/asm/device.h
---- linux-2.6.34.1/arch/microblaze/include/asm/device.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/microblaze/include/asm/device.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -16,7 +16,7 @@ struct dev_archdata {
- 	struct device_node	*of_node;
- 
- 	/* DMA operations on that device */
--	struct dma_map_ops	*dma_ops;
-+	const struct dma_map_ops	*dma_ops;
- 	void                    *dma_data;
- };
- 
-diff -urNp linux-2.6.34.1/arch/microblaze/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/microblaze/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/microblaze/include/asm/dma-mapping.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/microblaze/include/asm/dma-mapping.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -43,14 +43,14 @@ static inline unsigned long device_to_ma
- 	return 0xfffffffful;
- }
- 
--extern struct dma_map_ops *dma_ops;
-+extern const struct dma_map_ops *dma_ops;
- 
- /*
-  * Available generic sets of operations
-  */
--extern struct dma_map_ops dma_direct_ops;
-+extern const struct dma_map_ops dma_direct_ops;
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- 	/* We don't handle the NULL dev case for ISA for now. We could
- 	 * do it via an out of line call but it is not needed for now. The
-@@ -63,14 +63,14 @@ static inline struct dma_map_ops *get_dm
- 	return dev->archdata.dma_ops;
- }
- 
--static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
-+static inline void set_dma_ops(struct device *dev, const struct dma_map_ops *ops)
- {
- 	dev->archdata.dma_ops = ops;
- }
- 
- static inline int dma_supported(struct device *dev, u64 mask)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (unlikely(!ops))
- 		return 0;
-@@ -87,7 +87,7 @@ static inline int dma_supported(struct d
- 
- static inline int dma_set_mask(struct device *dev, u64 dma_mask)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (unlikely(ops == NULL))
- 		return -EIO;
-@@ -103,7 +103,7 @@ static inline int dma_set_mask(struct de
- 
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	if (ops->mapping_error)
- 		return ops->mapping_error(dev, dma_addr);
- 
-@@ -117,7 +117,7 @@ static inline int dma_mapping_error(stru
- static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- 					dma_addr_t *dma_handle, gfp_t flag)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	void *memory;
- 
- 	BUG_ON(!ops);
-@@ -131,7 +131,7 @@ static inline void *dma_alloc_coherent(s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *cpu_addr, dma_addr_t dma_handle)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	BUG_ON(!ops);
- 	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
-diff -urNp linux-2.6.34.1/arch/microblaze/include/asm/pci.h \
                linux-2.6.34.1/arch/microblaze/include/asm/pci.h
---- linux-2.6.34.1/arch/microblaze/include/asm/pci.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/microblaze/include/asm/pci.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -54,8 +54,8 @@ static inline void pcibios_penalize_isa_
- }
- 
- #ifdef CONFIG_PCI
--extern void set_pci_dma_ops(struct dma_map_ops *dma_ops);
--extern struct dma_map_ops *get_pci_dma_ops(void);
-+extern void set_pci_dma_ops(const struct dma_map_ops *dma_ops);
-+extern const struct dma_map_ops *get_pci_dma_ops(void);
- #else	/* CONFIG_PCI */
- #define set_pci_dma_ops(d)
- #define get_pci_dma_ops()	NULL
-diff -urNp linux-2.6.34.1/arch/microblaze/kernel/dma.c \
                linux-2.6.34.1/arch/microblaze/kernel/dma.c
---- linux-2.6.34.1/arch/microblaze/kernel/dma.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/microblaze/kernel/dma.c	2010-07-07 09:04:42.000000000 -0400
-@@ -134,7 +134,7 @@ static inline void dma_direct_unmap_page
- 	__dma_sync_page(dma_address, 0 , size, direction);
- }
- 
--struct dma_map_ops dma_direct_ops = {
-+const struct dma_map_ops dma_direct_ops = {
- 	.alloc_coherent	= dma_direct_alloc_coherent,
- 	.free_coherent	= dma_direct_free_coherent,
- 	.map_sg		= dma_direct_map_sg,
-diff -urNp linux-2.6.34.1/arch/microblaze/pci/pci-common.c \
                linux-2.6.34.1/arch/microblaze/pci/pci-common.c
---- linux-2.6.34.1/arch/microblaze/pci/pci-common.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/microblaze/pci/pci-common.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -46,14 +46,14 @@ resource_size_t isa_mem_base;
- /* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
- unsigned int pci_flags;
- 
--static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
-+static const struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
- 
--void set_pci_dma_ops(struct dma_map_ops *dma_ops)
-+void set_pci_dma_ops(const struct dma_map_ops *dma_ops)
- {
- 	pci_dma_ops = dma_ops;
- }
- 
--struct dma_map_ops *get_pci_dma_ops(void)
-+const struct dma_map_ops *get_pci_dma_ops(void)
- {
- 	return pci_dma_ops;
- }
-diff -urNp linux-2.6.34.1/arch/mips/alchemy/devboards/pm.c \
                linux-2.6.34.1/arch/mips/alchemy/devboards/pm.c
---- linux-2.6.34.1/arch/mips/alchemy/devboards/pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/mips/alchemy/devboards/pm.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -110,7 +110,7 @@ static void db1x_pm_end(void)
- 
- }
- 
--static struct platform_suspend_ops db1x_pm_ops = {
-+static const struct platform_suspend_ops db1x_pm_ops = {
- 	.valid		= suspend_valid_only_mem,
- 	.begin		= db1x_pm_begin,
- 	.enter		= db1x_pm_enter,
-diff -urNp linux-2.6.34.1/arch/mips/include/asm/elf.h \
                linux-2.6.34.1/arch/mips/include/asm/elf.h
---- linux-2.6.34.1/arch/mips/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -368,6 +368,13 @@ extern const char *__elf_platform;
- #define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
- #endif
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : \
                0x00400000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#endif
-+
- #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
- struct linux_binprm;
- extern int arch_setup_additional_pages(struct linux_binprm *bprm,
-diff -urNp linux-2.6.34.1/arch/mips/include/asm/page.h \
                linux-2.6.34.1/arch/mips/include/asm/page.h
---- linux-2.6.34.1/arch/mips/include/asm/page.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/include/asm/page.h	2010-07-07 09:04:42.000000000 -0400
-@@ -93,7 +93,7 @@ extern void copy_user_highpage(struct pa
-   #ifdef CONFIG_CPU_MIPS32
-     typedef struct { unsigned long pte_low, pte_high; } pte_t;
-     #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
--    #define __pte(x)      ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; \
                __pte; })
-+    #define __pte(x)      ({ pte_t __pte = {(x), (x) >> 32}; __pte; })
-   #else
-      typedef struct { unsigned long long pte; } pte_t;
-      #define pte_val(x)	((x).pte)
-diff -urNp linux-2.6.34.1/arch/mips/include/asm/system.h \
                linux-2.6.34.1/arch/mips/include/asm/system.h
---- linux-2.6.34.1/arch/mips/include/asm/system.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/mips/include/asm/system.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -234,6 +234,6 @@ extern void per_cpu_trap_init(void);
-  */
- #define __ARCH_WANT_UNLOCKED_CTXSW
- 
--extern unsigned long arch_align_stack(unsigned long sp);
-+#define arch_align_stack(x) ((x) & ALMASK)
- 
- #endif /* _ASM_SYSTEM_H */
-diff -urNp linux-2.6.34.1/arch/mips/kernel/binfmt_elfn32.c \
                linux-2.6.34.1/arch/mips/kernel/binfmt_elfn32.c
---- linux-2.6.34.1/arch/mips/kernel/binfmt_elfn32.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/mips/kernel/binfmt_elfn32.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
- #undef ELF_ET_DYN_BASE
- #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : \
                0x00400000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#endif
-+
- #include <asm/processor.h>
- #include <linux/module.h>
- #include <linux/elfcore.h>
-diff -urNp linux-2.6.34.1/arch/mips/kernel/binfmt_elfo32.c \
                linux-2.6.34.1/arch/mips/kernel/binfmt_elfo32.c
---- linux-2.6.34.1/arch/mips/kernel/binfmt_elfo32.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/mips/kernel/binfmt_elfo32.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
- #undef ELF_ET_DYN_BASE
- #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : \
                0x00400000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : \
                36-PAGE_SHIFT)
-+#endif
-+
- #include <asm/processor.h>
- 
- /*
-diff -urNp linux-2.6.34.1/arch/mips/kernel/kgdb.c \
                linux-2.6.34.1/arch/mips/kernel/kgdb.c
---- linux-2.6.34.1/arch/mips/kernel/kgdb.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/kernel/kgdb.c	2010-07-07 09:04:42.000000000 -0400
-@@ -245,6 +245,7 @@ int kgdb_arch_handle_exception(int vecto
- 	return -1;
- }
- 
-+/* cannot be const, see kgdb_arch_init */
- struct kgdb_arch arch_kgdb_ops;
- 
- /*
-diff -urNp linux-2.6.34.1/arch/mips/kernel/process.c \
                linux-2.6.34.1/arch/mips/kernel/process.c
---- linux-2.6.34.1/arch/mips/kernel/process.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/kernel/process.c	2010-07-07 09:04:42.000000000 -0400
-@@ -474,15 +474,3 @@ unsigned long get_wchan(struct task_stru
- out:
- 	return pc;
- }
--
--/*
-- * Don't forget that the stack pointer must be aligned on a 8 bytes
-- * boundary for 32-bits ABI and 16 bytes for 64-bits ABI.
-- */
--unsigned long arch_align_stack(unsigned long sp)
--{
--	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
--		sp -= get_random_int() & ~PAGE_MASK;
--
--	return sp & ALMASK;
--}
-diff -urNp linux-2.6.34.1/arch/mips/kernel/syscall.c \
                linux-2.6.34.1/arch/mips/kernel/syscall.c
---- linux-2.6.34.1/arch/mips/kernel/syscall.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/kernel/syscall.c	2010-07-07 09:04:42.000000000 -0400
-@@ -106,6 +106,11 @@ unsigned long arch_get_unmapped_area(str
- 	do_color_align = 0;
- 	if (filp || (flags & MAP_SHARED))
- 		do_color_align = 1;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
-+#endif
-+
- 	if (addr) {
- 		if (do_color_align)
- 			addr = COLOUR_ALIGN(addr, pgoff);
-@@ -116,7 +121,7 @@ unsigned long arch_get_unmapped_area(str
- 		    (!vmm || addr + len <= vmm->vm_start))
- 			return addr;
- 	}
--	addr = TASK_UNMAPPED_BASE;
-+	addr = current->mm->mmap_base;
- 	if (do_color_align)
- 		addr = COLOUR_ALIGN(addr, pgoff);
- 	else
-diff -urNp linux-2.6.34.1/arch/mips/loongson/common/pm.c \
                linux-2.6.34.1/arch/mips/loongson/common/pm.c
---- linux-2.6.34.1/arch/mips/loongson/common/pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/mips/loongson/common/pm.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -147,7 +147,7 @@ static int loongson_pm_valid_state(suspe
- 	}
- }
- 
--static struct platform_suspend_ops loongson_pm_ops = {
-+static const struct platform_suspend_ops loongson_pm_ops = {
- 	.valid	= loongson_pm_valid_state,
- 	.enter	= loongson_pm_enter,
- };
-diff -urNp linux-2.6.34.1/arch/mips/mm/fault.c linux-2.6.34.1/arch/mips/mm/fault.c
---- linux-2.6.34.1/arch/mips/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/mips/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -26,6 +26,23 @@
- #include <asm/ptrace.h>
- #include <asm/highmem.h>		/* For VMALLOC_END */
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+void pax_report_insns(void *pc)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 5; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- /*
-  * This routine handles page faults.  It determines the address,
-  * and the problem, and then passes it off to one of the appropriate
-diff -urNp linux-2.6.34.1/arch/parisc/include/asm/elf.h \
                linux-2.6.34.1/arch/parisc/include/asm/elf.h
---- linux-2.6.34.1/arch/parisc/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/parisc/include/asm/elf.h	2010-07-07 09:04:42.000000000 -0400
-@@ -342,6 +342,13 @@ struct pt_regs;	/* forward declaration..
- 
- #define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE + 0x01000000)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	0x10000UL
-+
-+#define PAX_DELTA_MMAP_LEN	16
-+#define PAX_DELTA_STACK_LEN	16
-+#endif
-+
- /* 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,
-    but it's not easy, and we've already done it here.  */
-diff -urNp linux-2.6.34.1/arch/parisc/include/asm/pgtable.h \
                linux-2.6.34.1/arch/parisc/include/asm/pgtable.h
---- linux-2.6.34.1/arch/parisc/include/asm/pgtable.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/parisc/include/asm/pgtable.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -207,6 +207,17 @@
- #define PAGE_EXECREAD   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
                _PAGE_EXEC |_PAGE_ACCESSED)
- #define PAGE_COPY       PAGE_EXECREAD
- #define PAGE_RWX        __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
                _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+# define PAGE_SHARED_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
                _PAGE_WRITE | _PAGE_ACCESSED)
-+# define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
                _PAGE_ACCESSED)
-+# define PAGE_READONLY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | \
                _PAGE_ACCESSED)
-+#else
-+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
-+# define PAGE_COPY_NOEXEC	PAGE_COPY
-+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
-+#endif
-+
- #define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
- #define PAGE_KERNEL_RO	__pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
- #define PAGE_KERNEL_UNC	__pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
-diff -urNp linux-2.6.34.1/arch/parisc/kernel/module.c \
                linux-2.6.34.1/arch/parisc/kernel/module.c
---- linux-2.6.34.1/arch/parisc/kernel/module.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/parisc/kernel/module.c	2010-07-07 09:04:42.000000000 -0400
-@@ -96,16 +96,38 @@
- 
- /* three functions to determine where in the module core
-  * or init pieces the location is */
-+static inline int in_init_rx(struct module *me, void *loc)
-+{
-+	return (loc >= me->module_init_rx &&
-+		loc < (me->module_init_rx + me->init_size_rx));
-+}
-+
-+static inline int in_init_rw(struct module *me, void *loc)
-+{
-+	return (loc >= me->module_init_rw &&
-+		loc < (me->module_init_rw + me->init_size_rw));
-+}
-+
- static inline int in_init(struct module *me, void *loc)
- {
--	return (loc >= me->module_init &&
--		loc <= (me->module_init + me->init_size));
-+	return in_init_rx(me, loc) || in_init_rw(me, loc);
-+}
-+
-+static inline int in_core_rx(struct module *me, void *loc)
-+{
-+	return (loc >= me->module_core_rx &&
-+		loc < (me->module_core_rx + me->core_size_rx));
-+}
-+
-+static inline int in_core_rw(struct module *me, void *loc)
-+{
-+	return (loc >= me->module_core_rw &&
-+		loc < (me->module_core_rw + me->core_size_rw));
- }
- 
- static inline int in_core(struct module *me, void *loc)
- {
--	return (loc >= me->module_core &&
--		loc <= (me->module_core + me->core_size));
-+	return in_core_rx(me, loc) || in_core_rw(me, loc);
- }
- 
- static inline int in_local(struct module *me, void *loc)
-@@ -365,13 +387,13 @@ int module_frob_arch_sections(CONST Elf_
- 	}
- 
- 	/* align things a bit */
--	me->core_size = ALIGN(me->core_size, 16);
--	me->arch.got_offset = me->core_size;
--	me->core_size += gots * sizeof(struct got_entry);
--
--	me->core_size = ALIGN(me->core_size, 16);
--	me->arch.fdesc_offset = me->core_size;
--	me->core_size += fdescs * sizeof(Elf_Fdesc);
-+	me->core_size_rw = ALIGN(me->core_size_rw, 16);
-+	me->arch.got_offset = me->core_size_rw;
-+	me->core_size_rw += gots * sizeof(struct got_entry);
-+
-+	me->core_size_rw = ALIGN(me->core_size_rw, 16);
-+	me->arch.fdesc_offset = me->core_size_rw;
-+	me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
- 
- 	me->arch.got_max = gots;
- 	me->arch.fdesc_max = fdescs;
-@@ -389,7 +411,7 @@ static Elf64_Word get_got(struct module 
- 
- 	BUG_ON(value == 0);
- 
--	got = me->module_core + me->arch.got_offset;
-+	got = me->module_core_rw + me->arch.got_offset;
- 	for (i = 0; got[i].addr; i++)
- 		if (got[i].addr == value)
- 			goto out;
-@@ -407,7 +429,7 @@ static Elf64_Word get_got(struct module 
- #ifdef CONFIG_64BIT
- static Elf_Addr get_fdesc(struct module *me, unsigned long value)
- {
--	Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
-+	Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
- 
- 	if (!value) {
- 		printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
-@@ -425,7 +447,7 @@ static Elf_Addr get_fdesc(struct module 
- 
- 	/* Create new one */
- 	fdesc->addr = value;
--	fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
-+	fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
- 	return (Elf_Addr)fdesc;
- }
- #endif /* CONFIG_64BIT */
-@@ -849,7 +871,7 @@ register_unwind_table(struct module *me,
- 
- 	table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
- 	end = table + sechdrs[me->arch.unwind_section].sh_size;
--	gp = (Elf_Addr)me->module_core + me->arch.got_offset;
-+	gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
- 
- 	DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
- 	       me->arch.unwind_section, table, end, gp);
-diff -urNp linux-2.6.34.1/arch/parisc/kernel/sys_parisc.c \
                linux-2.6.34.1/arch/parisc/kernel/sys_parisc.c
---- linux-2.6.34.1/arch/parisc/kernel/sys_parisc.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/parisc/kernel/sys_parisc.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -98,7 +98,7 @@ unsigned long arch_get_unmapped_area(str
- 	if (flags & MAP_FIXED)
- 		return addr;
- 	if (!addr)
--		addr = TASK_UNMAPPED_BASE;
-+		addr = current->mm->mmap_base;
- 
- 	if (filp) {
- 		addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
-diff -urNp linux-2.6.34.1/arch/parisc/kernel/traps.c \
                linux-2.6.34.1/arch/parisc/kernel/traps.c
---- linux-2.6.34.1/arch/parisc/kernel/traps.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/parisc/kernel/traps.c	2010-07-07 09:04:42.000000000 -0400
-@@ -733,9 +733,7 @@ void notrace handle_interruption(int cod
- 
- 			down_read(&current->mm->mmap_sem);
- 			vma = find_vma(current->mm,regs->iaoq[0]);
--			if (vma && (regs->iaoq[0] >= vma->vm_start)
--				&& (vma->vm_flags & VM_EXEC)) {
--
-+			if (vma && (regs->iaoq[0] >= vma->vm_start)) {
- 				fault_address = regs->iaoq[0];
- 				fault_space = regs->iasq[0];
- 
-diff -urNp linux-2.6.34.1/arch/parisc/mm/fault.c \
                linux-2.6.34.1/arch/parisc/mm/fault.c
---- linux-2.6.34.1/arch/parisc/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/parisc/mm/fault.c	2010-07-07 09:04:42.000000000 -0400
-@@ -15,6 +15,7 @@
- #include <linux/sched.h>
- #include <linux/interrupt.h>
- #include <linux/module.h>
-+#include <linux/unistd.h>
- 
- #include <asm/uaccess.h>
- #include <asm/traps.h>
-@@ -52,7 +53,7 @@ DEFINE_PER_CPU(struct exception_data, ex
- static unsigned long
- parisc_acctyp(unsigned long code, unsigned int inst)
- {
--	if (code == 6 || code == 16)
-+	if (code == 6 || code == 7 || code == 16)
- 	    return VM_EXEC;
- 
- 	switch (inst & 0xf0000000) {
-@@ -138,6 +139,116 @@ parisc_acctyp(unsigned long code, unsign
- 			}
- #endif
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+/*
-+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault \
                address)
-+ *
-+ * returns 1 when task should be killed
-+ *         2 when rt_sigreturn trampoline was detected
-+ *         3 when unpatched PLT trampoline was detected
-+ */
-+static int pax_handle_fetch_fault(struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+	int err;
-+
-+	do { /* PaX: unpatched PLT emulation */
-+		unsigned int bl, depwi;
-+
-+		err = get_user(bl, (unsigned int *)instruction_pointer(regs));
-+		err |= get_user(depwi, (unsigned int *)(instruction_pointer(regs)+4));
-+
-+		if (err)
-+			break;
-+
-+		if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
-+			unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
-+
-+			err = get_user(ldw, (unsigned int *)addr);
-+			err |= get_user(bv, (unsigned int *)(addr+4));
-+			err |= get_user(ldw2, (unsigned int *)(addr+8));
-+
-+			if (err)
-+				break;
-+
-+			if (ldw == 0x0E801096U &&
-+			    bv == 0xEAC0C000U &&
-+			    ldw2 == 0x0E881095U)
-+			{
-+				unsigned int resolver, map;
-+
-+				err = get_user(resolver, (unsigned int *)(instruction_pointer(regs)+8));
-+				err |= get_user(map, (unsigned int *)(instruction_pointer(regs)+12));
-+				if (err)
-+					break;
-+
-+				regs->gr[20] = instruction_pointer(regs)+8;
-+				regs->gr[21] = map;
-+				regs->gr[22] = resolver;
-+				regs->iaoq[0] = resolver | 3UL;
-+				regs->iaoq[1] = regs->iaoq[0] + 4;
-+				return 3;
-+			}
-+		}
-+	} while (0);
-+#endif
-+
-+#ifdef CONFIG_PAX_EMUTRAMP
-+
-+#ifndef CONFIG_PAX_EMUSIGRT
-+	if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
-+		return 1;
-+#endif
-+
-+	do { /* PaX: rt_sigreturn emulation */
-+		unsigned int ldi1, ldi2, bel, nop;
-+
-+		err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
-+		err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
-+		err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
-+		err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
-+
-+		if (err)
-+			break;
-+
-+		if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
-+		    ldi2 == 0x3414015AU &&
-+		    bel == 0xE4008200U &&
-+		    nop == 0x08000240U)
-+		{
-+			regs->gr[25] = (ldi1 & 2) >> 1;
-+			regs->gr[20] = __NR_rt_sigreturn;
-+			regs->gr[31] = regs->iaoq[1] + 16;
-+			regs->sr[0] = regs->iasq[1];
-+			regs->iaoq[0] = 0x100UL;
-+			regs->iaoq[1] = regs->iaoq[0] + 4;
-+			regs->iasq[0] = regs->sr[2];
-+			regs->iasq[1] = regs->sr[2];
-+			return 2;
-+		}
-+	} while (0);
-+#endif
-+
-+	return 1;
-+}
-+
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 5; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- int fixup_exception(struct pt_regs *regs)
- {
- 	const struct exception_table_entry *fix;
-@@ -192,8 +303,33 @@ good_area:
- 
- 	acc_type = parisc_acctyp(code,regs->iir);
- 
--	if ((vma->vm_flags & acc_type) != acc_type)
-+	if ((vma->vm_flags & acc_type) != acc_type) {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
-+		    (address & ~3UL) == instruction_pointer(regs))
-+		{
-+			up_read(&mm->mmap_sem);
-+			switch (pax_handle_fetch_fault(regs)) {
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+			case 3:
-+				return;
-+#endif
-+
-+#ifdef CONFIG_PAX_EMUTRAMP
-+			case 2:
-+				return;
-+#endif
-+
-+			}
-+			pax_report_fault(regs, (void *)instruction_pointer(regs), (void *)regs->gr[30]);
-+			do_group_exit(SIGKILL);
-+		}
-+#endif
-+
- 		goto bad_area;
-+	}
- 
- 	/*
- 	 * If for any reason at all we couldn't handle the fault, make
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/device.h \
                linux-2.6.34.1/arch/powerpc/include/asm/device.h
---- linux-2.6.34.1/arch/powerpc/include/asm/device.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/device.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -14,7 +14,7 @@ struct dev_archdata {
- 	struct device_node	*of_node;
- 
- 	/* DMA operations on that device */
--	struct dma_map_ops	*dma_ops;
-+	const struct dma_map_ops	*dma_ops;
- 
- 	/*
- 	 * When an iommu is in use, dma_data is used as a ptr to the base of the
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/powerpc/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/powerpc/include/asm/dma-mapping.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/dma-mapping.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -67,11 +67,11 @@ static inline unsigned long device_to_ma
-  * Available generic sets of operations
-  */
- #ifdef CONFIG_PPC64
--extern struct dma_map_ops dma_iommu_ops;
-+extern const struct dma_map_ops dma_iommu_ops;
- #endif
--extern struct dma_map_ops dma_direct_ops;
-+extern const struct dma_map_ops dma_direct_ops;
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- 	/* We don't handle the NULL dev case for ISA for now. We could
- 	 * do it via an out of line call but it is not needed for now. The
-@@ -84,7 +84,7 @@ static inline struct dma_map_ops *get_dm
- 	return dev->archdata.dma_ops;
- }
- 
--static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
-+static inline void set_dma_ops(struct device *dev, const struct dma_map_ops *ops)
- {
- 	dev->archdata.dma_ops = ops;
- }
-@@ -118,7 +118,7 @@ static inline void set_dma_offset(struct
- 
- static inline int dma_supported(struct device *dev, u64 mask)
- {
--	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-+	const struct dma_map_ops *dma_ops = get_dma_ops(dev);
- 
- 	if (unlikely(dma_ops == NULL))
- 		return 0;
-@@ -129,7 +129,7 @@ static inline int dma_supported(struct d
- 
- static inline int dma_set_mask(struct device *dev, u64 dma_mask)
- {
--	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-+	const struct dma_map_ops *dma_ops = get_dma_ops(dev);
- 
- 	if (unlikely(dma_ops == NULL))
- 		return -EIO;
-@@ -144,7 +144,7 @@ static inline int dma_set_mask(struct de
- static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- 				       dma_addr_t *dma_handle, gfp_t flag)
- {
--	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-+	const struct dma_map_ops *dma_ops = get_dma_ops(dev);
- 	void *cpu_addr;
- 
- 	BUG_ON(!dma_ops);
-@@ -159,7 +159,7 @@ static inline void *dma_alloc_coherent(s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *cpu_addr, dma_addr_t dma_handle)
- {
--	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-+	const struct dma_map_ops *dma_ops = get_dma_ops(dev);
- 
- 	BUG_ON(!dma_ops);
- 
-@@ -170,7 +170,7 @@ static inline void dma_free_coherent(str
- 
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
--	struct dma_map_ops *dma_ops = get_dma_ops(dev);
-+	const struct dma_map_ops *dma_ops = get_dma_ops(dev);
- 
- 	if (dma_ops->mapping_error)
- 		return dma_ops->mapping_error(dev, dma_addr);
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/elf.h \
                linux-2.6.34.1/arch/powerpc/include/asm/elf.h
---- linux-2.6.34.1/arch/powerpc/include/asm/elf.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/elf.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -178,8 +178,19 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[E
-    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.  */
- 
--extern unsigned long randomize_et_dyn(unsigned long base);
--#define ELF_ET_DYN_BASE		(randomize_et_dyn(0x20000000))
-+#define ELF_ET_DYN_BASE		(0x20000000)
-+
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(0x10000000UL)
-+
-+#ifdef __powerpc64__
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_32BIT) ? 16 : 28)
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_32BIT) ? 16 : 28)
-+#else
-+#define PAX_DELTA_MMAP_LEN	15
-+#define PAX_DELTA_STACK_LEN	15
-+#endif
-+#endif
- 
- /*
-  * Our registers are always unsigned longs, whether we're a 32 bit
-@@ -274,9 +285,6 @@ extern int arch_setup_additional_pages(s
- 	(0x7ff >> (PAGE_SHIFT - 12)) : \
- 	(0x3ffff >> (PAGE_SHIFT - 12)))
- 
--extern unsigned long arch_randomize_brk(struct mm_struct *mm);
--#define arch_randomize_brk arch_randomize_brk
--
- #endif /* __KERNEL__ */
- 
- /*
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/iommu.h \
                linux-2.6.34.1/arch/powerpc/include/asm/iommu.h
---- linux-2.6.34.1/arch/powerpc/include/asm/iommu.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/iommu.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -116,6 +116,9 @@ extern void iommu_init_early_iSeries(voi
- extern void iommu_init_early_dart(void);
- extern void iommu_init_early_pasemi(void);
- 
-+/* dma-iommu.c */
-+extern int dma_iommu_dma_supported(struct device *dev, u64 mask);
-+
- #ifdef CONFIG_PCI
- extern void pci_iommu_init(void);
- extern void pci_direct_iommu_init(void);
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/kmap_types.h \
                linux-2.6.34.1/arch/powerpc/include/asm/kmap_types.h
---- linux-2.6.34.1/arch/powerpc/include/asm/kmap_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/kmap_types.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -26,6 +26,7 @@ enum km_type {
- 	KM_SOFTIRQ1,
- 	KM_PPC_SYNC_PAGE,
- 	KM_PPC_SYNC_ICACHE,
-+	KM_CLEARPAGE,
- 	KM_TYPE_NR
- };
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/page.h \
                linux-2.6.34.1/arch/powerpc/include/asm/page.h
---- linux-2.6.34.1/arch/powerpc/include/asm/page.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/page.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -129,8 +129,9 @@ extern phys_addr_t kernstart_addr;
-  * and needs to be executable.  This means the whole heap ends
-  * up being executable.
-  */
--#define VM_DATA_DEFAULT_FLAGS32	(VM_READ | VM_WRITE | VM_EXEC | \
--				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-+#define VM_DATA_DEFAULT_FLAGS32 \
-+	(((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
-+	 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
- 
- #define VM_DATA_DEFAULT_FLAGS64	(VM_READ | VM_WRITE | \
- 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-@@ -158,6 +159,9 @@ extern phys_addr_t kernstart_addr;
- #define is_kernel_addr(x)	((x) >= PAGE_OFFSET)
- #endif
- 
-+#define ktla_ktva(addr)		(addr)
-+#define ktva_ktla(addr)		(addr)
-+
- #ifndef __ASSEMBLY__
- 
- #undef STRICT_MM_TYPECHECKS
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/page_64.h \
                linux-2.6.34.1/arch/powerpc/include/asm/page_64.h
---- linux-2.6.34.1/arch/powerpc/include/asm/page_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/page_64.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -180,15 +180,18 @@ do {						\
-  * stack by default, so in the absense of a PT_GNU_STACK program header
-  * we turn execute permission off.
-  */
--#define VM_STACK_DEFAULT_FLAGS32	(VM_READ | VM_WRITE | VM_EXEC | \
--					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-+#define VM_STACK_DEFAULT_FLAGS32 \
-+	(((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
-+	 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
- 
- #define VM_STACK_DEFAULT_FLAGS64	(VM_READ | VM_WRITE | \
- 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
- 
-+#ifndef CONFIG_PAX_PAGEEXEC
- #define VM_STACK_DEFAULT_FLAGS \
- 	(test_thread_flag(TIF_32BIT) ? \
- 	 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
-+#endif
- 
- #include <asm-generic/getorder.h>
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/pci.h \
                linux-2.6.34.1/arch/powerpc/include/asm/pci.h
---- linux-2.6.34.1/arch/powerpc/include/asm/pci.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/pci.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -65,8 +65,8 @@ static inline int pci_get_legacy_ide_irq
- }
- 
- #ifdef CONFIG_PCI
--extern void set_pci_dma_ops(struct dma_map_ops *dma_ops);
--extern struct dma_map_ops *get_pci_dma_ops(void);
-+extern void set_pci_dma_ops(const struct dma_map_ops *dma_ops);
-+extern const struct dma_map_ops *get_pci_dma_ops(void);
- #else	/* CONFIG_PCI */
- #define set_pci_dma_ops(d)
- #define get_pci_dma_ops()	NULL
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/pte-hash32.h \
                linux-2.6.34.1/arch/powerpc/include/asm/pte-hash32.h
---- linux-2.6.34.1/arch/powerpc/include/asm/pte-hash32.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/pte-hash32.h	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -21,6 +21,7 @@
- #define _PAGE_FILE	0x004	/* when !present: nonlinear file mapping */
- #define _PAGE_USER	0x004	/* usermode access allowed */
- #define _PAGE_GUARDED	0x008	/* G: prohibit speculative access */
-+#define _PAGE_EXEC	_PAGE_GUARDED
- #define _PAGE_COHERENT	0x010	/* M: enforce memory coherence (SMP systems) */
- #define _PAGE_NO_CACHE	0x020	/* I: cache inhibit */
- #define _PAGE_WRITETHRU	0x040	/* W: cache write-through */
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/reg.h \
                linux-2.6.34.1/arch/powerpc/include/asm/reg.h
---- linux-2.6.34.1/arch/powerpc/include/asm/reg.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/reg.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -191,6 +191,7 @@
- #define SPRN_DBCR	0x136	/* e300 Data Breakpoint Control Reg */
- #define SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
- #define   DSISR_NOHPTE		0x40000000	/* no translation found */
-+#define   DSISR_GUARDED		0x10000000	/* fetch from guarded storage */
- #define   DSISR_PROTFAULT	0x08000000	/* protection fault */
- #define   DSISR_ISSTORE		0x02000000	/* access was a store */
- #define   DSISR_DABRMATCH	0x00400000	/* hit data breakpoint */
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/swiotlb.h \
                linux-2.6.34.1/arch/powerpc/include/asm/swiotlb.h
---- linux-2.6.34.1/arch/powerpc/include/asm/swiotlb.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/swiotlb.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -13,7 +13,7 @@
- 
- #include <linux/swiotlb.h>
- 
--extern struct dma_map_ops swiotlb_dma_ops;
-+extern const struct dma_map_ops swiotlb_dma_ops;
- 
- static inline void dma_mark_clean(void *addr, size_t size) {}
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/include/asm/uaccess.h \
                linux-2.6.34.1/arch/powerpc/include/asm/uaccess.h
---- linux-2.6.34.1/arch/powerpc/include/asm/uaccess.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/include/asm/uaccess.h	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -13,6 +13,8 @@
- #define VERIFY_READ	0
- #define VERIFY_WRITE	1
- 
-+extern void check_object_size(const void *ptr, unsigned long n, bool to);
-+
- /*
-  * The fs value determines whether argument validity checking should be
-  * performed or not.  If get_fs() == USER_DS, checking is performed, with
-@@ -327,52 +329,6 @@ do {								\
- extern unsigned long __copy_tofrom_user(void __user *to,
- 		const void __user *from, unsigned long size);
- 
--#ifndef __powerpc64__
--
--static inline unsigned long copy_from_user(void *to,
--		const void __user *from, unsigned long n)
--{
--	unsigned long over;
--
--	if (access_ok(VERIFY_READ, from, n))
--		return __copy_tofrom_user((__force void __user *)to, from, n);
--	if ((unsigned long)from < TASK_SIZE) {
--		over = (unsigned long)from + n - TASK_SIZE;
--		return __copy_tofrom_user((__force void __user *)to, from,
--				n - over) + over;
--	}
--	return n;
--}
--
--static inline unsigned long copy_to_user(void __user *to,
--		const void *from, unsigned long n)
--{
--	unsigned long over;
--
--	if (access_ok(VERIFY_WRITE, to, n))
--		return __copy_tofrom_user(to, (__force void __user *)from, n);
--	if ((unsigned long)to < TASK_SIZE) {
--		over = (unsigned long)to + n - TASK_SIZE;
--		return __copy_tofrom_user(to, (__force void __user *)from,
--				n - over) + over;
--	}
--	return n;
--}
--
--#else /* __powerpc64__ */
--
--#define __copy_in_user(to, from, size) \
--	__copy_tofrom_user((to), (from), (size))
--
--extern unsigned long copy_from_user(void *to, const void __user *from,
--				    unsigned long n);
--extern unsigned long copy_to_user(void __user *to, const void *from,
--				  unsigned long n);
--extern unsigned long copy_in_user(void __user *to, const void __user *from,
--				  unsigned long n);
--
--#endif /* __powerpc64__ */
--
- static inline unsigned long __copy_from_user_inatomic(void *to,
- 		const void __user *from, unsigned long n)
- {
-@@ -396,6 +352,10 @@ static inline unsigned long __copy_from_
- 		if (ret == 0)
- 			return 0;
- 	}
-+
-+	if (!__builtin_constant_p(n))
-+		check_object_size(to, n, false);
-+
- 	return __copy_tofrom_user((__force void __user *)to, from, n);
- }
- 
-@@ -422,6 +382,10 @@ static inline unsigned long __copy_to_us
- 		if (ret == 0)
- 			return 0;
- 	}
-+
-+	if (!__builtin_constant_p(n))
-+		check_object_size(from, n, true);
-+
- 	return __copy_tofrom_user(to, (__force const void __user *)from, n);
- }
- 
-@@ -439,6 +403,92 @@ static inline unsigned long __copy_to_us
- 	return __copy_to_user_inatomic(to, from, size);
- }
- 
-+#ifndef __powerpc64__
-+
-+static inline unsigned long __must_check copy_from_user(void *to,
-+		const void __user *from, unsigned long n)
-+{
-+	unsigned long over;
-+
-+	if ((long)n < 0)
-+		return n;
-+
-+	if (access_ok(VERIFY_READ, from, n)) {
-+		if (!__builtin_constant_p(n))
-+			check_object_size(to, n, false);
-+		return __copy_tofrom_user((__force void __user *)to, from, n);
-+	}
-+	if ((unsigned long)from < TASK_SIZE) {
-+		over = (unsigned long)from + n - TASK_SIZE;
-+		if (!__builtin_constant_p(n - over))
-+			check_object_size(to, n - over, false);
-+		return __copy_tofrom_user((__force void __user *)to, from,
-+				n - over) + over;
-+	}
-+	return n;
-+}
-+
-+static inline unsigned long __must_check copy_to_user(void __user *to,
-+		const void *from, unsigned long n)
-+{
-+	unsigned long over;
-+
-+	if ((long)n < 0)
-+		return n;
-+
-+	if (access_ok(VERIFY_WRITE, to, n)) {
-+		if (!__builtin_constant_p(n))
-+			check_object_size(from, n, true);
-+		return __copy_tofrom_user(to, (__force void __user *)from, n);
-+	}
-+	if ((unsigned long)to < TASK_SIZE) {
-+		over = (unsigned long)to + n - TASK_SIZE;
-+		if (!__builtin_constant_p(n))
-+			check_object_size(from, n - over, true);
-+		return __copy_tofrom_user(to, (__force void __user *)from,
-+				n - over) + over;
-+	}
-+	return n;
-+}
-+
-+#else /* __powerpc64__ */
-+
-+#define __copy_in_user(to, from, size) \
-+	__copy_tofrom_user((to), (from), (size))
-+
-+static inline unsigned long __must_check copy_from_user(void *to, const void __user \
                *from, unsigned long n)
-+{
-+	if ((long)n < 0 || n > INT_MAX)
-+		return n;
-+
-+	if (!__builtin_constant_p(n))
-+		check_object_size(to, n, false);
-+
-+	if (likely(access_ok(VERIFY_READ, from, n)))
-+		n = __copy_from_user(to, from, n);
-+	else
-+		memset(to, 0, n);
-+	return n;
-+}
-+
-+static inline unsigned long __must_check copy_to_user(void __user *to, const void \
                *from, unsigned long n)
-+{
-+	if ((long)n < 0 || n > INT_MAX)
-+		return n;
-+
-+	if (likely(access_ok(VERIFY_WRITE, to, n))) {
-+		if (!__builtin_constant_p(n))
-+			check_object_size(from, n, true);
-+		n = __copy_to_user(to, from, n);
-+	}
-+	return n;
-+}
-+
-+extern unsigned long copy_in_user(void __user *to, const void __user *from,
-+				  unsigned long n);
-+
-+#endif /* __powerpc64__ */
-+
- extern unsigned long __clear_user(void __user *addr, unsigned long size);
- 
- static inline unsigned long clear_user(void __user *addr, unsigned long size)
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/dma-iommu.c \
                linux-2.6.34.1/arch/powerpc/kernel/dma-iommu.c
---- linux-2.6.34.1/arch/powerpc/kernel/dma-iommu.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/dma-iommu.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -70,7 +70,7 @@ static void dma_iommu_unmap_sg(struct de
- }
- 
- /* We support DMA to/from any memory page via the iommu */
--static int dma_iommu_dma_supported(struct device *dev, u64 mask)
-+int dma_iommu_dma_supported(struct device *dev, u64 mask)
- {
- 	struct iommu_table *tbl = get_iommu_table_base(dev);
- 
-@@ -89,7 +89,7 @@ static int dma_iommu_dma_supported(struc
- 		return 1;
- }
- 
--struct dma_map_ops dma_iommu_ops = {
-+const struct dma_map_ops dma_iommu_ops = {
- 	.alloc_coherent	= dma_iommu_alloc_coherent,
- 	.free_coherent	= dma_iommu_free_coherent,
- 	.map_sg		= dma_iommu_map_sg,
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/dma-swiotlb.c \
                linux-2.6.34.1/arch/powerpc/kernel/dma-swiotlb.c
---- linux-2.6.34.1/arch/powerpc/kernel/dma-swiotlb.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/dma-swiotlb.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -31,7 +31,7 @@ unsigned int ppc_swiotlb_enable;
-  * map_page, and unmap_page on highmem, use normal dma_ops
-  * for everything else.
-  */
--struct dma_map_ops swiotlb_dma_ops = {
-+const struct dma_map_ops swiotlb_dma_ops = {
- 	.alloc_coherent = dma_direct_alloc_coherent,
- 	.free_coherent = dma_direct_free_coherent,
- 	.map_sg = swiotlb_map_sg_attrs,
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/dma.c \
                linux-2.6.34.1/arch/powerpc/kernel/dma.c
---- linux-2.6.34.1/arch/powerpc/kernel/dma.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/dma.c	2010-07-07 09:04:42.000000000 -0400
-@@ -135,7 +135,7 @@ static inline void dma_direct_sync_singl
- }
- #endif
- 
--struct dma_map_ops dma_direct_ops = {
-+const struct dma_map_ops dma_direct_ops = {
- 	.alloc_coherent	= dma_direct_alloc_coherent,
- 	.free_coherent	= dma_direct_free_coherent,
- 	.map_sg		= dma_direct_map_sg,
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/exceptions-64e.S \
                linux-2.6.34.1/arch/powerpc/kernel/exceptions-64e.S
---- linux-2.6.34.1/arch/powerpc/kernel/exceptions-64e.S	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/exceptions-64e.S	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -455,6 +455,7 @@ storage_fault_common:
- 	std	r14,_DAR(r1)
- 	std	r15,_DSISR(r1)
- 	addi	r3,r1,STACK_FRAME_OVERHEAD
-+	bl	.save_nvgprs
- 	mr	r4,r14
- 	mr	r5,r15
- 	ld	r14,PACA_EXGEN+EX_R14(r13)
-@@ -464,8 +465,7 @@ storage_fault_common:
- 	cmpdi	r3,0
- 	bne-	1f
- 	b	.ret_from_except_lite
--1:	bl	.save_nvgprs
--	mr	r5,r3
-+1:	mr	r5,r3
- 	addi	r3,r1,STACK_FRAME_OVERHEAD
- 	ld	r4,_DAR(r1)
- 	bl	.bad_page_fault
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/exceptions-64s.S \
                linux-2.6.34.1/arch/powerpc/kernel/exceptions-64s.S
---- linux-2.6.34.1/arch/powerpc/kernel/exceptions-64s.S	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/exceptions-64s.S	2010-07-07 \
                09:04:42.000000000 -0400
-@@ -829,10 +829,10 @@ handle_page_fault:
- 11:	ld	r4,_DAR(r1)
- 	ld	r5,_DSISR(r1)
- 	addi	r3,r1,STACK_FRAME_OVERHEAD
-+	bl	.save_nvgprs
- 	bl	.do_page_fault
- 	cmpdi	r3,0
- 	beq+	13f
--	bl	.save_nvgprs
- 	mr	r5,r3
- 	addi	r3,r1,STACK_FRAME_OVERHEAD
- 	lwz	r4,_DAR(r1)
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/ibmebus.c \
                linux-2.6.34.1/arch/powerpc/kernel/ibmebus.c
---- linux-2.6.34.1/arch/powerpc/kernel/ibmebus.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/ibmebus.c	2010-07-07 09:04:42.000000000 -0400
-@@ -128,7 +128,7 @@ static int ibmebus_dma_supported(struct 
- 	return 1;
- }
- 
--static struct dma_map_ops ibmebus_dma_ops = {
-+static const struct dma_map_ops ibmebus_dma_ops = {
- 	.alloc_coherent = ibmebus_alloc_coherent,
- 	.free_coherent  = ibmebus_free_coherent,
- 	.map_sg         = ibmebus_map_sg,
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/kgdb.c \
                linux-2.6.34.1/arch/powerpc/kernel/kgdb.c
---- linux-2.6.34.1/arch/powerpc/kernel/kgdb.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/kgdb.c	2010-07-07 09:04:42.000000000 -0400
-@@ -126,7 +126,7 @@ static int kgdb_handle_breakpoint(struct
- 	if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
- 		return 0;
- 
--	if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
-+	if (*(u32 *) (regs->nip) == *(const u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
- 		regs->nip += 4;
- 
- 	return 1;
-@@ -353,7 +353,7 @@ int kgdb_arch_handle_exception(int vecto
- /*
-  * Global data
-  */
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- 	.gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
- };
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/module.c \
                linux-2.6.34.1/arch/powerpc/kernel/module.c
---- linux-2.6.34.1/arch/powerpc/kernel/module.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/module.c	2010-07-07 09:04:42.000000000 -0400
-@@ -31,11 +31,24 @@
- 
- LIST_HEAD(module_bug_list);
- 
-+#ifdef CONFIG_PAX_KERNEXEC
- void *module_alloc(unsigned long size)
- {
- 	if (size == 0)
- 		return NULL;
- 
-+	return vmalloc(size);
-+}
-+
-+void *module_alloc_exec(unsigned long size)
-+#else
-+void *module_alloc(unsigned long size)
-+#endif
-+
-+{
-+	if (size == 0)
-+		return NULL;
-+
- 	return vmalloc_exec(size);
- }
- 
-@@ -45,6 +58,13 @@ void module_free(struct module *mod, voi
- 	vfree(module_region);
- }
- 
-+#ifdef CONFIG_PAX_KERNEXEC
-+void module_free_exec(struct module *mod, void *module_region)
-+{
-+	module_free(mod, module_region);
-+}
-+#endif
-+
- static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
- 				    const Elf_Shdr *sechdrs,
- 				    const char *name)
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/module_32.c \
                linux-2.6.34.1/arch/powerpc/kernel/module_32.c
---- linux-2.6.34.1/arch/powerpc/kernel/module_32.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/module_32.c	2010-07-07 09:04:42.000000000 \
                -0400
-@@ -162,7 +162,7 @@ int module_frob_arch_sections(Elf32_Ehdr
- 			me->arch.core_plt_section = i;
- 	}
- 	if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
--		printk("Module doesn't contain .plt or .init.plt sections.\n");
-+		printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name);
- 		return -ENOEXEC;
- 	}
- 
-@@ -203,11 +203,16 @@ static uint32_t do_plt_call(void *locati
- 
- 	DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
- 	/* Init, or core PLT? */
--	if (location >= mod->module_core
--	    && location < mod->module_core + mod->core_size)
-+	if ((location >= mod->module_core_rx && location < mod->module_core_rx + \
                mod->core_size_rx) ||
-+	    (location >= mod->module_core_rw && location < mod->module_core_rw + \
                mod->core_size_rw))
- 		entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
--	else
-+	else if ((location >= mod->module_init_rx && location < mod->module_init_rx + \
                mod->init_size_rx) ||
-+		 (location >= mod->module_init_rw && location < mod->module_init_rw + \
                mod->init_size_rw))
- 		entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
-+	else {
-+		printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name);
-+		return ~0UL;
-+	}
- 
- 	/* Find this entry, or if that fails, the next avail. entry */
- 	while (entry->jump[0]) {
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/pci-common.c \
                linux-2.6.34.1/arch/powerpc/kernel/pci-common.c
---- linux-2.6.34.1/arch/powerpc/kernel/pci-common.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/pci-common.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -51,14 +51,14 @@ resource_size_t isa_mem_base;
- unsigned int ppc_pci_flags = 0;
- 
- 
--static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
-+static const struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
- 
--void set_pci_dma_ops(struct dma_map_ops *dma_ops)
-+void set_pci_dma_ops(const struct dma_map_ops *dma_ops)
- {
- 	pci_dma_ops = dma_ops;
- }
- 
--struct dma_map_ops *get_pci_dma_ops(void)
-+const struct dma_map_ops *get_pci_dma_ops(void)
- {
- 	return pci_dma_ops;
- }
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/process.c \
                linux-2.6.34.1/arch/powerpc/kernel/process.c
---- linux-2.6.34.1/arch/powerpc/kernel/process.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/process.c	2010-07-07 09:04:43.000000000 -0400
-@@ -1217,51 +1217,3 @@ unsigned long arch_align_stack(unsigned 
- 		sp -= get_random_int() & ~PAGE_MASK;
- 	return sp & ~0xf;
- }
--
--static inline unsigned long brk_rnd(void)
--{
--        unsigned long rnd = 0;
--
--	/* 8MB for 32bit, 1GB for 64bit */
--	if (is_32bit_task())
--		rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
--	else
--		rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
--
--	return rnd << PAGE_SHIFT;
--}
--
--unsigned long arch_randomize_brk(struct mm_struct *mm)
--{
--	unsigned long base = mm->brk;
--	unsigned long ret;
--
--#ifdef CONFIG_PPC_STD_MMU_64
--	/*
--	 * If we are using 1TB segments and we are allowed to randomise
--	 * the heap, we can put it above 1TB so it is backed by a 1TB
--	 * segment. Otherwise the heap will be in the bottom 1TB
--	 * which always uses 256MB segments and this may result in a
--	 * performance penalty.
--	 */
--	if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
--		base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
--#endif
--
--	ret = PAGE_ALIGN(base + brk_rnd());
--
--	if (ret < mm->brk)
--		return mm->brk;
--
--	return ret;
--}
--
--unsigned long randomize_et_dyn(unsigned long base)
--{
--	unsigned long ret = PAGE_ALIGN(base + brk_rnd());
--
--	if (ret < base)
--		return base;
--
--	return ret;
--}
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/signal_32.c \
                linux-2.6.34.1/arch/powerpc/kernel/signal_32.c
---- linux-2.6.34.1/arch/powerpc/kernel/signal_32.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/signal_32.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -857,7 +857,7 @@ int handle_rt_signal32(unsigned long sig
- 	/* Save user registers on the stack */
- 	frame = &rt_sf->uc.uc_mcontext;
- 	addr = frame;
--	if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
-+	if (vdso32_rt_sigtramp && current->mm->context.vdso_base != ~0UL) {
- 		if (save_user_regs(regs, frame, 0, 1))
- 			goto badframe;
- 		regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/signal_64.c \
                linux-2.6.34.1/arch/powerpc/kernel/signal_64.c
---- linux-2.6.34.1/arch/powerpc/kernel/signal_64.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/signal_64.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -429,7 +429,7 @@ int handle_rt_signal64(int signr, struct
- 	current->thread.fpscr.val = 0;
- 
- 	/* Set up to return from userspace. */
--	if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
-+	if (vdso64_rt_sigtramp && current->mm->context.vdso_base != ~0UL) {
- 		regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
- 	} else {
- 		err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/vdso.c \
                linux-2.6.34.1/arch/powerpc/kernel/vdso.c
---- linux-2.6.34.1/arch/powerpc/kernel/vdso.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/vdso.c	2010-07-07 09:04:43.000000000 -0400
-@@ -36,6 +36,7 @@
- #include <asm/firmware.h>
- #include <asm/vdso.h>
- #include <asm/vdso_datapage.h>
-+#include <asm/mman.h>
- 
- #include "setup.h"
- 
-@@ -220,7 +221,7 @@ int arch_setup_additional_pages(struct l
- 	vdso_base = VDSO32_MBASE;
- #endif
- 
--	current->mm->context.vdso_base = 0;
-+	current->mm->context.vdso_base = ~0UL;
- 
- 	/* vDSO has a problem and was disabled, just don't "enable" it for the
- 	 * process
-@@ -240,7 +241,7 @@ int arch_setup_additional_pages(struct l
- 	vdso_base = get_unmapped_area(NULL, vdso_base,
- 				      (vdso_pages << PAGE_SHIFT) +
- 				      ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
--				      0, 0);
-+				      0, MAP_PRIVATE | MAP_EXECUTABLE);
- 	if (IS_ERR_VALUE(vdso_base)) {
- 		rc = vdso_base;
- 		goto fail_mmapsem;
-diff -urNp linux-2.6.34.1/arch/powerpc/kernel/vio.c \
                linux-2.6.34.1/arch/powerpc/kernel/vio.c
---- linux-2.6.34.1/arch/powerpc/kernel/vio.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/kernel/vio.c	2010-07-07 09:04:43.000000000 -0400
-@@ -602,11 +602,12 @@ static void vio_dma_iommu_unmap_sg(struc
- 	vio_cmo_dealloc(viodev, alloc_size);
- }
- 
--struct dma_map_ops vio_dma_mapping_ops = {
-+static const struct dma_map_ops vio_dma_mapping_ops = {
- 	.alloc_coherent = vio_dma_iommu_alloc_coherent,
- 	.free_coherent  = vio_dma_iommu_free_coherent,
- 	.map_sg         = vio_dma_iommu_map_sg,
- 	.unmap_sg       = vio_dma_iommu_unmap_sg,
-+	.dma_supported  = dma_iommu_dma_supported,
- 	.map_page       = vio_dma_iommu_map_page,
- 	.unmap_page     = vio_dma_iommu_unmap_page,
- 
-@@ -858,7 +859,6 @@ static void vio_cmo_bus_remove(struct vi
- 
- static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
- {
--	vio_dma_mapping_ops.dma_supported = dma_iommu_ops.dma_supported;
- 	viodev->dev.archdata.dma_ops = &vio_dma_mapping_ops;
- }
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/lib/usercopy_64.c \
                linux-2.6.34.1/arch/powerpc/lib/usercopy_64.c
---- linux-2.6.34.1/arch/powerpc/lib/usercopy_64.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/lib/usercopy_64.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -9,22 +9,6 @@
- #include <linux/module.h>
- #include <asm/uaccess.h>
- 
--unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
--{
--	if (likely(access_ok(VERIFY_READ, from, n)))
--		n = __copy_from_user(to, from, n);
--	else
--		memset(to, 0, n);
--	return n;
--}
--
--unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
--{
--	if (likely(access_ok(VERIFY_WRITE, to, n)))
--		n = __copy_to_user(to, from, n);
--	return n;
--}
--
- unsigned long copy_in_user(void __user *to, const void __user *from,
- 			   unsigned long n)
- {
-@@ -35,7 +19,5 @@ unsigned long copy_in_user(void __user *
- 	return n;
- }
- 
--EXPORT_SYMBOL(copy_from_user);
--EXPORT_SYMBOL(copy_to_user);
- EXPORT_SYMBOL(copy_in_user);
- 
-diff -urNp linux-2.6.34.1/arch/powerpc/mm/fault.c \
                linux-2.6.34.1/arch/powerpc/mm/fault.c
---- linux-2.6.34.1/arch/powerpc/mm/fault.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/mm/fault.c	2010-07-07 09:04:43.000000000 -0400
-@@ -30,6 +30,10 @@
- #include <linux/kprobes.h>
- #include <linux/kdebug.h>
- #include <linux/perf_event.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/compiler.h>
-+#include <linux/unistd.h>
- 
- #include <asm/firmware.h>
- #include <asm/page.h>
-@@ -41,6 +45,7 @@
- #include <asm/tlbflush.h>
- #include <asm/siginfo.h>
- #include <mm/mmu_decl.h>
-+#include <asm/ptrace.h>
- 
- #ifdef CONFIG_KPROBES
- static inline int notify_page_fault(struct pt_regs *regs)
-@@ -64,6 +69,33 @@ static inline int notify_page_fault(stru
- }
- #endif
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+/*
-+ * PaX: decide what to do with offenders (regs->nip = fault address)
-+ *
-+ * returns 1 when task should be killed
-+ */
-+static int pax_handle_fetch_fault(struct pt_regs *regs)
-+{
-+	return 1;
-+}
-+
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 5; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int __user *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- /*
-  * Check whether the instruction at regs->nip is a store using
-  * an update addressing form which will update r1.
-@@ -134,7 +166,7 @@ int __kprobes do_page_fault(struct pt_re
- 	 * indicate errors in DSISR but can validly be set in SRR1.
- 	 */
- 	if (trap == 0x400)
--		error_code &= 0x48200000;
-+		error_code &= 0x58200000;
- 	else
- 		is_write = error_code & DSISR_ISSTORE;
- #else
-@@ -256,7 +288,7 @@ good_area:
-          * "undefined".  Of those that can be set, this is the only
-          * one which seems bad.
-          */
--	if (error_code & 0x10000000)
-+	if (error_code & DSISR_GUARDED)
-                 /* Guarded storage error. */
- 		goto bad_area;
- #endif /* CONFIG_8xx */
-@@ -271,7 +303,7 @@ good_area:
- 		 * processors use the same I/D cache coherency mechanism
- 		 * as embedded.
- 		 */
--		if (error_code & DSISR_PROTFAULT)
-+		if (error_code & (DSISR_PROTFAULT | DSISR_GUARDED))
- 			goto bad_area;
- #endif /* CONFIG_PPC_STD_MMU */
- 
-@@ -341,6 +373,23 @@ bad_area:
- bad_area_nosemaphore:
- 	/* User mode accesses cause a SIGSEGV */
- 	if (user_mode(regs)) {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if (mm->pax_flags & MF_PAX_PAGEEXEC) {
-+#ifdef CONFIG_PPC_STD_MMU
-+			if (is_exec && (error_code & (DSISR_PROTFAULT | DSISR_GUARDED))) {
-+#else
-+			if (is_exec && regs->nip == address) {
-+#endif
-+				switch (pax_handle_fetch_fault(regs)) {
-+				}
-+
-+				pax_report_fault(regs, (void *)regs->nip, (void *)regs->gpr[PT_R1]);
-+				do_group_exit(SIGKILL);
-+			}
-+		}
-+#endif
-+
- 		_exception(SIGSEGV, regs, code, address);
- 		return 0;
- 	}
-diff -urNp linux-2.6.34.1/arch/powerpc/mm/mmap_64.c \
                linux-2.6.34.1/arch/powerpc/mm/mmap_64.c
---- linux-2.6.34.1/arch/powerpc/mm/mmap_64.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/mm/mmap_64.c	2010-07-07 09:04:43.000000000 -0400
-@@ -99,10 +99,22 @@ void arch_pick_mmap_layout(struct mm_str
- 	 */
- 	if (mmap_is_legacy()) {
- 		mm->mmap_base = TASK_UNMAPPED_BASE;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base += mm->delta_mmap;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area;
- 		mm->unmap_area = arch_unmap_area;
- 	} else {
- 		mm->mmap_base = mmap_base();
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
- 		mm->unmap_area = arch_unmap_area_topdown;
- 	}
-diff -urNp linux-2.6.34.1/arch/powerpc/mm/slice.c \
                linux-2.6.34.1/arch/powerpc/mm/slice.c
---- linux-2.6.34.1/arch/powerpc/mm/slice.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/mm/slice.c	2010-07-07 09:04:43.000000000 -0400
-@@ -426,6 +426,11 @@ unsigned long slice_get_unmapped_area(un
- 	if (fixed && addr > (mm->task_size - len))
- 		return -EINVAL;
- 
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (!fixed && (mm->pax_flags & MF_PAX_RANDMMAP))
-+		addr = 0;
-+#endif
-+
- 	/* If hint, make sure it matches our alignment restrictions */
- 	if (!fixed && addr) {
- 		addr = _ALIGN_UP(addr, 1ul << pshift);
-diff -urNp linux-2.6.34.1/arch/powerpc/platforms/52xx/lite5200_pm.c \
                linux-2.6.34.1/arch/powerpc/platforms/52xx/lite5200_pm.c
---- linux-2.6.34.1/arch/powerpc/platforms/52xx/lite5200_pm.c	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/platforms/52xx/lite5200_pm.c	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -235,7 +235,7 @@ static void lite5200_pm_end(void)
- 	lite5200_pm_target_state = PM_SUSPEND_ON;
- }
- 
--static struct platform_suspend_ops lite5200_pm_ops = {
-+static const struct platform_suspend_ops lite5200_pm_ops = {
- 	.valid		= lite5200_pm_valid,
- 	.begin		= lite5200_pm_begin,
- 	.prepare	= lite5200_pm_prepare,
-diff -urNp linux-2.6.34.1/arch/powerpc/platforms/52xx/mpc52xx_pm.c \
                linux-2.6.34.1/arch/powerpc/platforms/52xx/mpc52xx_pm.c
---- linux-2.6.34.1/arch/powerpc/platforms/52xx/mpc52xx_pm.c	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/platforms/52xx/mpc52xx_pm.c	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -180,7 +180,7 @@ void mpc52xx_pm_finish(void)
- 	iounmap(mbar);
- }
- 
--static struct platform_suspend_ops mpc52xx_pm_ops = {
-+static const struct platform_suspend_ops mpc52xx_pm_ops = {
- 	.valid		= mpc52xx_pm_valid,
- 	.prepare	= mpc52xx_pm_prepare,
- 	.enter		= mpc52xx_pm_enter,
-diff -urNp linux-2.6.34.1/arch/powerpc/platforms/83xx/suspend.c \
                linux-2.6.34.1/arch/powerpc/platforms/83xx/suspend.c
---- linux-2.6.34.1/arch/powerpc/platforms/83xx/suspend.c	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/platforms/83xx/suspend.c	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -311,7 +311,7 @@ static int mpc83xx_is_pci_agent(void)
- 	return ret;
- }
- 
--static struct platform_suspend_ops mpc83xx_suspend_ops = {
-+static const struct platform_suspend_ops mpc83xx_suspend_ops = {
- 	.valid = mpc83xx_suspend_valid,
- 	.begin = mpc83xx_suspend_begin,
- 	.enter = mpc83xx_suspend_enter,
-diff -urNp linux-2.6.34.1/arch/powerpc/platforms/cell/iommu.c \
                linux-2.6.34.1/arch/powerpc/platforms/cell/iommu.c
---- linux-2.6.34.1/arch/powerpc/platforms/cell/iommu.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/powerpc/platforms/cell/iommu.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -643,7 +643,7 @@ static int dma_fixed_dma_supported(struc
- 
- static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
- 
--struct dma_map_ops dma_iommu_fixed_ops = {
-+const struct dma_map_ops dma_iommu_fixed_ops = {
- 	.alloc_coherent = dma_fixed_alloc_coherent,
- 	.free_coherent  = dma_fixed_free_coherent,
- 	.map_sg         = dma_fixed_map_sg,
-diff -urNp linux-2.6.34.1/arch/powerpc/platforms/ps3/system-bus.c \
                linux-2.6.34.1/arch/powerpc/platforms/ps3/system-bus.c
---- linux-2.6.34.1/arch/powerpc/platforms/ps3/system-bus.c	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/platforms/ps3/system-bus.c	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -695,7 +695,7 @@ static int ps3_dma_supported(struct devi
- 	return mask >= DMA_BIT_MASK(32);
- }
- 
--static struct dma_map_ops ps3_sb_dma_ops = {
-+static const struct dma_map_ops ps3_sb_dma_ops = {
- 	.alloc_coherent = ps3_alloc_coherent,
- 	.free_coherent = ps3_free_coherent,
- 	.map_sg = ps3_sb_map_sg,
-@@ -705,7 +705,7 @@ static struct dma_map_ops ps3_sb_dma_ops
- 	.unmap_page = ps3_unmap_page,
- };
- 
--static struct dma_map_ops ps3_ioc0_dma_ops = {
-+static const struct dma_map_ops ps3_ioc0_dma_ops = {
- 	.alloc_coherent = ps3_alloc_coherent,
- 	.free_coherent = ps3_free_coherent,
- 	.map_sg = ps3_ioc0_map_sg,
-diff -urNp linux-2.6.34.1/arch/powerpc/sysdev/fsl_pmc.c \
                linux-2.6.34.1/arch/powerpc/sysdev/fsl_pmc.c
---- linux-2.6.34.1/arch/powerpc/sysdev/fsl_pmc.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/powerpc/sysdev/fsl_pmc.c	2010-07-07 09:04:43.000000000 -0400
-@@ -53,7 +53,7 @@ static int pmc_suspend_valid(suspend_sta
- 	return 1;
- }
- 
--static struct platform_suspend_ops pmc_suspend_ops = {
-+static const struct platform_suspend_ops pmc_suspend_ops = {
- 	.valid = pmc_suspend_valid,
- 	.enter = pmc_suspend_enter,
- };
-diff -urNp linux-2.6.34.1/arch/s390/Kconfig linux-2.6.34.1/arch/s390/Kconfig
---- linux-2.6.34.1/arch/s390/Kconfig	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/Kconfig	2010-07-07 09:04:43.000000000 -0400
-@@ -229,13 +229,12 @@ config AUDIT_ARCH
- 
- config S390_EXEC_PROTECT
- 	bool "Data execute protection"
-+	default y
- 	help
- 	  This option allows to enable a buffer overflow protection for user
--	  space programs and it also selects the addressing mode option above.
--	  The kernel parameter noexec=on will enable this feature and also
--	  switch the addressing modes, default is disabled. Enabling this (via
--	  kernel parameter) on machines earlier than IBM System z9-109 EC/BC
--	  will reduce system performance.
-+	  space programs.
-+	  Enabling this on machines earlier than IBM System z9-109 EC/BC will
-+	  reduce system performance.
- 
- comment "Code generation options"
- 
-diff -urNp linux-2.6.34.1/arch/s390/include/asm/elf.h \
                linux-2.6.34.1/arch/s390/include/asm/elf.h
---- linux-2.6.34.1/arch/s390/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/include/asm/elf.h	2010-07-07 09:04:43.000000000 -0400
-@@ -163,6 +163,13 @@ extern unsigned int vdso_enabled;
-    that it will "exec", and that there is sufficient room for the brk.  */
- #define ELF_ET_DYN_BASE		(STACK_TOP / 3 * 2)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(test_thread_flag(TIF_31BIT) ? 0x10000UL : \
                0x80000000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_31BIT) ? 15 : 26 )
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_31BIT) ? 15 : 26 )
-+#endif
-+
- /* This yields a mask that user programs can use to figure out what
-    instruction set this CPU supports. */
- 
-diff -urNp linux-2.6.34.1/arch/s390/include/asm/uaccess.h \
                linux-2.6.34.1/arch/s390/include/asm/uaccess.h
---- linux-2.6.34.1/arch/s390/include/asm/uaccess.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/s390/include/asm/uaccess.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -234,6 +234,10 @@ static inline unsigned long __must_check
- copy_to_user(void __user *to, const void *from, unsigned long n)
- {
- 	might_fault();
-+
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (access_ok(VERIFY_WRITE, to, n))
- 		n = __copy_to_user(to, from, n);
- 	return n;
-@@ -259,6 +263,9 @@ copy_to_user(void __user *to, const void
- static inline unsigned long __must_check
- __copy_from_user(void *to, const void __user *from, unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (__builtin_constant_p(n) && (n <= 256))
- 		return uaccess.copy_from_user_small(n, from, to);
- 	else
-@@ -293,6 +300,10 @@ copy_from_user(void *to, const void __us
- 	unsigned int sz = __compiletime_object_size(to);
- 
- 	might_fault();
-+
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (unlikely(sz != -1 && sz < n)) {
- 		copy_from_user_overflow();
- 		return n;
-diff -urNp linux-2.6.34.1/arch/s390/kernel/module.c \
                linux-2.6.34.1/arch/s390/kernel/module.c
---- linux-2.6.34.1/arch/s390/kernel/module.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/kernel/module.c	2010-07-07 09:04:43.000000000 -0400
-@@ -166,11 +166,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
- 
- 	/* Increase core size by size of got & plt and set start
- 	   offsets for got and plt. */
--	me->core_size = ALIGN(me->core_size, 4);
--	me->arch.got_offset = me->core_size;
--	me->core_size += me->arch.got_size;
--	me->arch.plt_offset = me->core_size;
--	me->core_size += me->arch.plt_size;
-+	me->core_size_rw = ALIGN(me->core_size_rw, 4);
-+	me->arch.got_offset = me->core_size_rw;
-+	me->core_size_rw += me->arch.got_size;
-+	me->arch.plt_offset = me->core_size_rx;
-+	me->core_size_rx += me->arch.plt_size;
- 	return 0;
- }
- 
-@@ -256,7 +256,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 		if (info->got_initialized == 0) {
- 			Elf_Addr *gotent;
- 
--			gotent = me->module_core + me->arch.got_offset +
-+			gotent = me->module_core_rw + me->arch.got_offset +
- 				info->got_offset;
- 			*gotent = val;
- 			info->got_initialized = 1;
-@@ -280,7 +280,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 		else if (r_type == R_390_GOTENT ||
- 			 r_type == R_390_GOTPLTENT)
- 			*(unsigned int *) loc =
--				(val + (Elf_Addr) me->module_core - loc) >> 1;
-+				(val + (Elf_Addr) me->module_core_rw - loc) >> 1;
- 		else if (r_type == R_390_GOT64 ||
- 			 r_type == R_390_GOTPLT64)
- 			*(unsigned long *) loc = val;
-@@ -294,7 +294,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 	case R_390_PLTOFF64:	/* 16 bit offset from GOT to PLT. */
- 		if (info->plt_initialized == 0) {
- 			unsigned int *ip;
--			ip = me->module_core + me->arch.plt_offset +
-+			ip = me->module_core_rx + me->arch.plt_offset +
- 				info->plt_offset;
- #ifndef CONFIG_64BIT
- 			ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
-@@ -319,7 +319,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 			       val - loc + 0xffffUL < 0x1ffffeUL) ||
- 			      (r_type == R_390_PLT32DBL &&
- 			       val - loc + 0xffffffffULL < 0x1fffffffeULL)))
--				val = (Elf_Addr) me->module_core +
-+				val = (Elf_Addr) me->module_core_rx +
- 					me->arch.plt_offset +
- 					info->plt_offset;
- 			val += rela->r_addend - loc;
-@@ -341,7 +341,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 	case R_390_GOTOFF32:	/* 32 bit offset to GOT.  */
- 	case R_390_GOTOFF64:	/* 64 bit offset to GOT. */
- 		val = val + rela->r_addend -
--			((Elf_Addr) me->module_core + me->arch.got_offset);
-+			((Elf_Addr) me->module_core_rw + me->arch.got_offset);
- 		if (r_type == R_390_GOTOFF16)
- 			*(unsigned short *) loc = val;
- 		else if (r_type == R_390_GOTOFF32)
-@@ -351,7 +351,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
- 		break;
- 	case R_390_GOTPC:	/* 32 bit PC relative offset to GOT. */
- 	case R_390_GOTPCDBL:	/* 32 bit PC rel. off. to GOT shifted by 1. */
--		val = (Elf_Addr) me->module_core + me->arch.got_offset +
-+		val = (Elf_Addr) me->module_core_rw + me->arch.got_offset +
- 			rela->r_addend - loc;
- 		if (r_type == R_390_GOTPC)
- 			*(unsigned int *) loc = val;
-diff -urNp linux-2.6.34.1/arch/s390/kernel/setup.c \
                linux-2.6.34.1/arch/s390/kernel/setup.c
---- linux-2.6.34.1/arch/s390/kernel/setup.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/kernel/setup.c	2010-07-07 09:04:43.000000000 -0400
-@@ -297,7 +297,7 @@ static int __init early_parse_mem(char *
- }
- early_param("mem", early_parse_mem);
- 
--unsigned int user_mode = HOME_SPACE_MODE;
-+unsigned int user_mode = SECONDARY_SPACE_MODE;
- EXPORT_SYMBOL_GPL(user_mode);
- 
- static int set_amode_and_uaccess(unsigned long user_amode,
-@@ -326,17 +326,6 @@ static int set_amode_and_uaccess(unsigne
- 	}
- }
- 
--/*
-- * Switch kernel/user addressing modes?
-- */
--static int __init early_parse_switch_amode(char *p)
--{
--	if (user_mode != SECONDARY_SPACE_MODE)
--		user_mode = PRIMARY_SPACE_MODE;
--	return 0;
--}
--early_param("switch_amode", early_parse_switch_amode);
--
- static int __init early_parse_user_mode(char *p)
- {
- 	if (p && strcmp(p, "primary") == 0)
-@@ -353,20 +342,6 @@ static int __init early_parse_user_mode(
- }
- early_param("user_mode", early_parse_user_mode);
- 
--#ifdef CONFIG_S390_EXEC_PROTECT
--/*
-- * Enable execute protection?
-- */
--static int __init early_parse_noexec(char *p)
--{
--	if (!strncmp(p, "off", 3))
--		return 0;
--	user_mode = SECONDARY_SPACE_MODE;
--	return 0;
--}
--early_param("noexec", early_parse_noexec);
--#endif /* CONFIG_S390_EXEC_PROTECT */
--
- static void setup_addressing_mode(void)
- {
- 	if (user_mode == SECONDARY_SPACE_MODE) {
-diff -urNp linux-2.6.34.1/arch/s390/mm/maccess.c \
                linux-2.6.34.1/arch/s390/mm/maccess.c
---- linux-2.6.34.1/arch/s390/mm/maccess.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/mm/maccess.c	2010-07-07 09:04:43.000000000 -0400
-@@ -45,7 +45,7 @@ static long probe_kernel_write_odd(void 
- 	return rc ? rc : count;
- }
- 
--long probe_kernel_write(void *dst, void *src, size_t size)
-+long probe_kernel_write(void *dst, const void *src, size_t size)
- {
- 	long copied = 0;
- 
-diff -urNp linux-2.6.34.1/arch/s390/mm/mmap.c linux-2.6.34.1/arch/s390/mm/mmap.c
---- linux-2.6.34.1/arch/s390/mm/mmap.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/s390/mm/mmap.c	2010-07-07 09:04:43.000000000 -0400
-@@ -78,10 +78,22 @@ void arch_pick_mmap_layout(struct mm_str
- 	 */
- 	if (mmap_is_legacy()) {
- 		mm->mmap_base = TASK_UNMAPPED_BASE;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base += mm->delta_mmap;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area;
- 		mm->unmap_area = arch_unmap_area;
- 	} else {
- 		mm->mmap_base = mmap_base();
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
- 		mm->unmap_area = arch_unmap_area_topdown;
- 	}
-@@ -153,10 +165,22 @@ void arch_pick_mmap_layout(struct mm_str
- 	 */
- 	if (mmap_is_legacy()) {
- 		mm->mmap_base = TASK_UNMAPPED_BASE;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base += mm->delta_mmap;
-+#endif
-+
- 		mm->get_unmapped_area = s390_get_unmapped_area;
- 		mm->unmap_area = arch_unmap_area;
- 	} else {
- 		mm->mmap_base = mmap_base();
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
-+#endif
-+
- 		mm->get_unmapped_area = s390_get_unmapped_area_topdown;
- 		mm->unmap_area = arch_unmap_area_topdown;
- 	}
-diff -urNp linux-2.6.34.1/arch/sh/boards/mach-hp6xx/pm.c \
                linux-2.6.34.1/arch/sh/boards/mach-hp6xx/pm.c
---- linux-2.6.34.1/arch/sh/boards/mach-hp6xx/pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sh/boards/mach-hp6xx/pm.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -143,7 +143,7 @@ static int hp6x0_pm_enter(suspend_state_
- 	return 0;
- }
- 
--static struct platform_suspend_ops hp6x0_pm_ops = {
-+static const struct platform_suspend_ops hp6x0_pm_ops = {
- 	.enter		= hp6x0_pm_enter,
- 	.valid		= suspend_valid_only_mem,
- };
-diff -urNp linux-2.6.34.1/arch/sh/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/sh/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/sh/include/asm/dma-mapping.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sh/include/asm/dma-mapping.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -1,10 +1,10 @@
- #ifndef __ASM_SH_DMA_MAPPING_H
- #define __ASM_SH_DMA_MAPPING_H
- 
--extern struct dma_map_ops *dma_ops;
-+extern const struct dma_map_ops *dma_ops;
- extern void no_iommu_init(void);
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- 	return dma_ops;
- }
-@@ -14,7 +14,7 @@ static inline struct dma_map_ops *get_dm
- 
- static inline int dma_supported(struct device *dev, u64 mask)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (ops->dma_supported)
- 		return ops->dma_supported(dev, mask);
-@@ -24,7 +24,7 @@ static inline int dma_supported(struct d
- 
- static inline int dma_set_mask(struct device *dev, u64 mask)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (!dev->dma_mask || !dma_supported(dev, mask))
- 		return -EIO;
-@@ -59,7 +59,7 @@ static inline int dma_get_cache_alignmen
- 
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (ops->mapping_error)
- 		return ops->mapping_error(dev, dma_addr);
-@@ -70,7 +70,7 @@ static inline int dma_mapping_error(stru
- static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- 				       dma_addr_t *dma_handle, gfp_t gfp)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	void *memory;
- 
- 	if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
-@@ -87,7 +87,7 @@ static inline void *dma_alloc_coherent(s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *vaddr, dma_addr_t dma_handle)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	if (dma_release_from_coherent(dev, get_order(size), vaddr))
- 		return;
-diff -urNp linux-2.6.34.1/arch/sh/kernel/cpu/shmobile/pm.c \
                linux-2.6.34.1/arch/sh/kernel/cpu/shmobile/pm.c
---- linux-2.6.34.1/arch/sh/kernel/cpu/shmobile/pm.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sh/kernel/cpu/shmobile/pm.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -141,7 +141,7 @@ static int sh_pm_enter(suspend_state_t s
- 	return 0;
- }
- 
--static struct platform_suspend_ops sh_pm_ops = {
-+static const struct platform_suspend_ops sh_pm_ops = {
- 	.enter          = sh_pm_enter,
- 	.valid          = suspend_valid_only_mem,
- };
-diff -urNp linux-2.6.34.1/arch/sh/kernel/dma-nommu.c \
                linux-2.6.34.1/arch/sh/kernel/dma-nommu.c
---- linux-2.6.34.1/arch/sh/kernel/dma-nommu.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sh/kernel/dma-nommu.c	2010-07-07 09:04:43.000000000 -0400
-@@ -62,7 +62,7 @@ static void nommu_sync_sg(struct device 
- }
- #endif
- 
--struct dma_map_ops nommu_dma_ops = {
-+const struct dma_map_ops nommu_dma_ops = {
- 	.alloc_coherent		= dma_generic_alloc_coherent,
- 	.free_coherent		= dma_generic_free_coherent,
- 	.map_page		= nommu_map_page,
-diff -urNp linux-2.6.34.1/arch/sh/kernel/kgdb.c linux-2.6.34.1/arch/sh/kernel/kgdb.c
---- linux-2.6.34.1/arch/sh/kernel/kgdb.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sh/kernel/kgdb.c	2010-07-07 09:04:43.000000000 -0400
-@@ -307,7 +307,7 @@ void kgdb_arch_exit(void)
- 	unregister_die_notifier(&kgdb_notifier);
- }
- 
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- 	/* Breakpoint instruction: trapa #0x3c */
- #ifdef CONFIG_CPU_LITTLE_ENDIAN
- 	.gdb_bpt_instr		= { 0x3c, 0xc3 },
-diff -urNp linux-2.6.34.1/arch/sh/mm/consistent.c \
                linux-2.6.34.1/arch/sh/mm/consistent.c
---- linux-2.6.34.1/arch/sh/mm/consistent.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sh/mm/consistent.c	2010-07-07 09:04:43.000000000 -0400
-@@ -22,7 +22,7 @@
- 
- #define PREALLOC_DMA_DEBUG_ENTRIES	4096
- 
--struct dma_map_ops *dma_ops;
-+const struct dma_map_ops *dma_ops;
- EXPORT_SYMBOL(dma_ops);
- 
- static int __init dma_init(void)
-diff -urNp linux-2.6.34.1/arch/sparc/Makefile linux-2.6.34.1/arch/sparc/Makefile
---- linux-2.6.34.1/arch/sparc/Makefile	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/Makefile	2010-07-07 09:04:44.000000000 -0400
-@@ -75,7 +75,7 @@ drivers-$(CONFIG_OPROFILE)	+= arch/sparc
- # Export what is needed by arch/sparc/boot/Makefile
- export VMLINUX_INIT VMLINUX_MAIN
- VMLINUX_INIT := $(head-y) $(init-y)
--VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/
-+VMLINUX_MAIN := $(core-y) kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
- VMLINUX_MAIN += $(patsubst %/, %/lib.a, $(libs-y)) $(libs-y)
- VMLINUX_MAIN += $(drivers-y) $(net-y)
- 
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/atomic_64.h \
                linux-2.6.34.1/arch/sparc/include/asm/atomic_64.h
---- linux-2.6.34.1/arch/sparc/include/asm/atomic_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/atomic_64.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -14,18 +14,39 @@
- #define ATOMIC64_INIT(i)	{ (i) }
- 
- #define atomic_read(v)		((v)->counter)
-+static inline int atomic_read_unchecked(const atomic_unchecked_t *v)
-+{
-+	return v->counter;
-+}
- #define atomic64_read(v)	((v)->counter)
-+static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v)
-+{
-+	return v->counter;
-+}
- 
- #define atomic_set(v, i)	(((v)->counter) = i)
-+static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i)
-+{
-+	v->counter = i;
-+}
- #define atomic64_set(v, i)	(((v)->counter) = i)
-+static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i)
-+{
-+	v->counter = i;
-+}
- 
- extern void atomic_add(int, atomic_t *);
-+extern void atomic_add_unchecked(int, atomic_unchecked_t *);
- extern void atomic64_add(int, atomic64_t *);
-+extern void atomic64_add_unchecked(int, atomic64_unchecked_t *);
- extern void atomic_sub(int, atomic_t *);
-+extern void atomic_sub_unchecked(int, atomic_unchecked_t *);
- extern void atomic64_sub(int, atomic64_t *);
-+extern void atomic64_sub_unchecked(int, atomic64_unchecked_t *);
- 
- extern int atomic_add_ret(int, atomic_t *);
- extern int atomic64_add_ret(int, atomic64_t *);
-+extern int atomic64_add_ret_unchecked(int, atomic64_unchecked_t *);
- extern int atomic_sub_ret(int, atomic_t *);
- extern int atomic64_sub_ret(int, atomic64_t *);
- 
-@@ -34,6 +55,7 @@ extern int atomic64_sub_ret(int, atomic6
- 
- #define atomic_inc_return(v) atomic_add_ret(1, v)
- #define atomic64_inc_return(v) atomic64_add_ret(1, v)
-+#define atomic64_inc_return_unchecked(v) atomic64_add_ret_unchecked(1, v)
- 
- #define atomic_sub_return(i, v) atomic_sub_ret(i, v)
- #define atomic64_sub_return(i, v) atomic64_sub_ret(i, v)
-@@ -59,10 +81,26 @@ extern int atomic64_sub_ret(int, atomic6
- #define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
- 
- #define atomic_inc(v) atomic_add(1, v)
-+static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
-+{
-+	atomic_add_unchecked(1, v);
-+}
- #define atomic64_inc(v) atomic64_add(1, v)
-+static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v)
-+{
-+	atomic64_add_unchecked(1, v);
-+}
- 
- #define atomic_dec(v) atomic_sub(1, v)
-+static inline void atomic_dec_unchecked(atomic_unchecked_t *v)
-+{
-+	atomic_sub_unchecked(1, v);
-+}
- #define atomic64_dec(v) atomic64_sub(1, v)
-+static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v)
-+{
-+	atomic64_sub_unchecked(1, v);
-+}
- 
- #define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
- #define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
-@@ -72,17 +110,28 @@ extern int atomic64_sub_ret(int, atomic6
- 
- static inline int atomic_add_unless(atomic_t *v, int a, int u)
- {
--	int c, old;
-+	int c, old, new;
- 	c = atomic_read(v);
- 	for (;;) {
--		if (unlikely(c == (u)))
-+		if (unlikely(c == u))
- 			break;
--		old = atomic_cmpxchg((v), c, c + (a));
-+
-+		asm volatile("addcc %2, %0, %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+			     "tvs %%icc, 6\n"
-+#endif
-+
-+			     : "=r" (new)
-+			     : "0" (c), "ir" (a)
-+			     : "cc");
-+
-+		old = atomic_cmpxchg(v, c, new);
- 		if (likely(old == c))
- 			break;
- 		c = old;
- 	}
--	return c != (u);
-+	return c != u;
- }
- 
- #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-@@ -93,17 +142,28 @@ static inline int atomic_add_unless(atom
- 
- static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
- {
--	long c, old;
-+	long c, old, new;
- 	c = atomic64_read(v);
- 	for (;;) {
--		if (unlikely(c == (u)))
-+		if (unlikely(c == u))
- 			break;
--		old = atomic64_cmpxchg((v), c, c + (a));
-+
-+		asm volatile("addcc %2, %0, %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+			     "tvs %%xcc, 6\n"
-+#endif
-+
-+			     : "=r" (new)
-+			     : "0" (c), "ir" (a)
-+			     : "cc");
-+
-+		old = atomic64_cmpxchg(v, c, new);
- 		if (likely(old == c))
- 			break;
- 		c = old;
- 	}
--	return c != (u);
-+	return c != u;
- }
- 
- #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/sparc/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/sparc/include/asm/dma-mapping.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/dma-mapping.h	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -13,10 +13,10 @@ extern int dma_supported(struct device *
- #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
- #define dma_is_consistent(d, h)	(1)
- 
--extern struct dma_map_ops *dma_ops, pci32_dma_ops;
-+extern const struct dma_map_ops *dma_ops, pci32_dma_ops;
- extern struct bus_type pci_bus_type;
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- #if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
- 	if (dev->bus == &pci_bus_type)
-@@ -30,7 +30,7 @@ static inline struct dma_map_ops *get_dm
- static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- 				       dma_addr_t *dma_handle, gfp_t flag)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	void *cpu_addr;
- 
- 	cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag);
-@@ -41,7 +41,7 @@ static inline void *dma_alloc_coherent(s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *cpu_addr, dma_addr_t dma_handle)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- 	ops->free_coherent(dev, size, cpu_addr, dma_handle);
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/elf_32.h \
                linux-2.6.34.1/arch/sparc/include/asm/elf_32.h
---- linux-2.6.34.1/arch/sparc/include/asm/elf_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/elf_32.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -114,6 +114,13 @@ typedef struct {
- 
- #define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE)
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	0x10000UL
-+
-+#define PAX_DELTA_MMAP_LEN	16
-+#define PAX_DELTA_STACK_LEN	16
-+#endif
-+
- /* This yields a mask that user programs can use to figure out what
-    instruction set this cpu supports.  This can NOT be done in userspace
-    on Sparc.  */
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/elf_64.h \
                linux-2.6.34.1/arch/sparc/include/asm/elf_64.h
---- linux-2.6.34.1/arch/sparc/include/asm/elf_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/elf_64.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -162,6 +162,12 @@ typedef struct {
- #define ELF_ET_DYN_BASE		0x0000010000000000UL
- #define COMPAT_ELF_ET_DYN_BASE	0x0000000070000000UL
- 
-+#ifdef CONFIG_PAX_ASLR
-+#define PAX_ELF_ET_DYN_BASE	(test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
-+
-+#define PAX_DELTA_MMAP_LEN	(test_thread_flag(TIF_32BIT) ? 14 : 28)
-+#define PAX_DELTA_STACK_LEN	(test_thread_flag(TIF_32BIT) ? 15 : 29)
-+#endif
- 
- /* This yields a mask that user programs can use to figure out what
-    instruction set this cpu supports.  */
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/pgtable_32.h \
                linux-2.6.34.1/arch/sparc/include/asm/pgtable_32.h
---- linux-2.6.34.1/arch/sparc/include/asm/pgtable_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/pgtable_32.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -43,6 +43,13 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
- BTFIXUPDEF_INT(page_none)
- BTFIXUPDEF_INT(page_copy)
- BTFIXUPDEF_INT(page_readonly)
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+BTFIXUPDEF_INT(page_shared_noexec)
-+BTFIXUPDEF_INT(page_copy_noexec)
-+BTFIXUPDEF_INT(page_readonly_noexec)
-+#endif
-+
- BTFIXUPDEF_INT(page_kernel)
- 
- #define PMD_SHIFT		SUN4C_PMD_SHIFT
-@@ -64,6 +71,16 @@ extern pgprot_t PAGE_SHARED;
- #define PAGE_COPY      __pgprot(BTFIXUP_INT(page_copy))
- #define PAGE_READONLY  __pgprot(BTFIXUP_INT(page_readonly))
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+extern pgprot_t PAGE_SHARED_NOEXEC;
-+# define PAGE_COPY_NOEXEC	__pgprot(BTFIXUP_INT(page_copy_noexec))
-+# define PAGE_READONLY_NOEXEC	__pgprot(BTFIXUP_INT(page_readonly_noexec))
-+#else
-+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
-+# define PAGE_COPY_NOEXEC	PAGE_COPY
-+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
-+#endif
-+
- extern unsigned long page_kernel;
- 
- #ifdef MODULE
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/pgtsrmmu.h \
                linux-2.6.34.1/arch/sparc/include/asm/pgtsrmmu.h
---- linux-2.6.34.1/arch/sparc/include/asm/pgtsrmmu.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/pgtsrmmu.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -115,6 +115,13 @@
- 				    SRMMU_EXEC | SRMMU_REF)
- #define SRMMU_PAGE_RDONLY  __pgprot(SRMMU_VALID | SRMMU_CACHE | \
- 				    SRMMU_EXEC | SRMMU_REF)
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+#define SRMMU_PAGE_SHARED_NOEXEC	__pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_WRITE | \
                SRMMU_REF)
-+#define SRMMU_PAGE_COPY_NOEXEC	__pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF)
-+#define SRMMU_PAGE_RDONLY_NOEXEC	__pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF)
-+#endif
-+
- #define SRMMU_PAGE_KERNEL  __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
- 				    SRMMU_DIRTY | SRMMU_REF)
- 
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/spinlock_64.h \
                linux-2.6.34.1/arch/sparc/include/asm/spinlock_64.h
---- linux-2.6.34.1/arch/sparc/include/asm/spinlock_64.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/spinlock_64.h	2010-07-07 \
                09:04:43.000000000 -0400
-@@ -99,7 +99,12 @@ static void inline arch_read_lock(arch_r
- 	__asm__ __volatile__ (
- "1:	ldsw		[%2], %0\n"
- "	brlz,pn		%0, 2f\n"
--"4:	 add		%0, 1, %1\n"
-+"4:	 addcc		%0, 1, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+"	tvs		%%icc, 6\n"
-+#endif
-+
- "	cas		[%2], %0, %1\n"
- "	cmp		%0, %1\n"
- "	bne,pn		%%icc, 1b\n"
-@@ -112,7 +117,7 @@ static void inline arch_read_lock(arch_r
- "	.previous"
- 	: "=&r" (tmp1), "=&r" (tmp2)
- 	: "r" (lock)
--	: "memory");
-+	: "memory", "cc");
- }
- 
- static int inline arch_read_trylock(arch_rwlock_t *lock)
-@@ -123,7 +128,12 @@ static int inline arch_read_trylock(arch
- "1:	ldsw		[%2], %0\n"
- "	brlz,a,pn	%0, 2f\n"
- "	 mov		0, %0\n"
--"	add		%0, 1, %1\n"
-+"	addcc		%0, 1, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+"	tvs		%%icc, 6\n"
-+#endif
-+
- "	cas		[%2], %0, %1\n"
- "	cmp		%0, %1\n"
- "	bne,pn		%%icc, 1b\n"
-@@ -142,7 +152,12 @@ static void inline arch_read_unlock(arch
- 
- 	__asm__ __volatile__(
- "1:	lduw	[%2], %0\n"
--"	sub	%0, 1, %1\n"
-+"	subcc	%0, 1, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+"	tvs	%%icc, 6\n"
-+#endif
-+
- "	cas	[%2], %0, %1\n"
- "	cmp	%0, %1\n"
- "	bne,pn	%%xcc, 1b\n"
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/uaccess.h \
                linux-2.6.34.1/arch/sparc/include/asm/uaccess.h
---- linux-2.6.34.1/arch/sparc/include/asm/uaccess.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/uaccess.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -1,5 +1,8 @@
- #ifndef ___ASM_SPARC_UACCESS_H
- #define ___ASM_SPARC_UACCESS_H
-+
-+extern void check_object_size(const void *ptr, unsigned long n, bool to);
-+
- #if defined(__sparc__) && defined(__arch64__)
- #include <asm/uaccess_64.h>
- #else
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/uaccess_32.h \
                linux-2.6.34.1/arch/sparc/include/asm/uaccess_32.h
---- linux-2.6.34.1/arch/sparc/include/asm/uaccess_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/uaccess_32.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -249,14 +249,25 @@ extern unsigned long __copy_user(void __
- 
- static inline unsigned long copy_to_user(void __user *to, const void *from, \
                unsigned long n)
- {
--	if (n && __access_ok((unsigned long) to, n))
-+	if ((long)n < 0)
-+		return n;
-+
-+	if (n && __access_ok((unsigned long) to, n)) {
-+		if (!__builtin_constant_p(n))
-+			check_object_size(from, n, true);
- 		return __copy_user(to, (__force void __user *) from, n);
--	else
-+	} else
- 		return n;
- }
- 
- static inline unsigned long __copy_to_user(void __user *to, const void *from, \
                unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
-+	if (!__builtin_constant_p(n))
-+		check_object_size(from, n, true);
-+
- 	return __copy_user(to, (__force void __user *) from, n);
- }
- 
-@@ -272,19 +283,27 @@ static inline unsigned long copy_from_us
- {
- 	int sz = __compiletime_object_size(to);
- 
-+	if ((long)n < 0)
-+		return n;
-+
- 	if (unlikely(sz != -1 && sz < n)) {
- 		copy_from_user_overflow();
- 		return n;
- 	}
- 
--	if (n && __access_ok((unsigned long) from, n))
-+	if (n && __access_ok((unsigned long) from, n)) {
-+		if (!__builtin_constant_p(n))
-+			check_object_size(to, n, false);
- 		return __copy_user((__force void __user *) to, from, n);
--	else
-+	} else
- 		return n;
- }
- 
- static inline unsigned long __copy_from_user(void *to, const void __user *from, \
                unsigned long n)
- {
-+	if ((long)n < 0)
-+		return n;
-+
- 	return __copy_user((__force void __user *) to, from, n);
- }
- 
-diff -urNp linux-2.6.34.1/arch/sparc/include/asm/uaccess_64.h \
                linux-2.6.34.1/arch/sparc/include/asm/uaccess_64.h
---- linux-2.6.34.1/arch/sparc/include/asm/uaccess_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/include/asm/uaccess_64.h	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -10,6 +10,7 @@
- #include <linux/compiler.h>
- #include <linux/string.h>
- #include <linux/thread_info.h>
-+#include <linux/kernel.h>
- #include <asm/asi.h>
- #include <asm/system.h>
- #include <asm/spitfire.h>
-@@ -224,6 +225,12 @@ copy_from_user(void *to, const void __us
- 	int sz = __compiletime_object_size(to);
- 	unsigned long ret = size;
- 
-+	if ((long)size < 0 || size > INT_MAX)
-+		return size;
-+
-+	if (!__builtin_constant_p(size))
-+		check_object_size(to, size, false);
-+
- 	if (likely(sz == -1 || sz >= size)) {
- 		ret = ___copy_from_user(to, from, size);
- 		if (unlikely(ret))
-@@ -243,8 +250,15 @@ extern unsigned long copy_to_user_fixup(
- static inline unsigned long __must_check
- copy_to_user(void __user *to, const void *from, unsigned long size)
- {
--	unsigned long ret = ___copy_to_user(to, from, size);
-+	unsigned long ret;
-+
-+	if ((long)size < 0 || size > INT_MAX)
-+		return size;
-+
-+	if (!__builtin_constant_p(size))
-+		check_object_size(from, size, true);
- 
-+	ret = ___copy_to_user(to, from, size);
- 	if (unlikely(ret))
- 		ret = copy_to_user_fixup(to, from, size);
- 	return ret;
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/Makefile \
                linux-2.6.34.1/arch/sparc/kernel/Makefile
---- linux-2.6.34.1/arch/sparc/kernel/Makefile	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/Makefile	2010-07-07 09:04:43.000000000 -0400
-@@ -3,7 +3,7 @@
- #
- 
- asflags-y := -ansi
--ccflags-y := -Werror
-+#ccflags-y := -Werror
- 
- extra-y     := head_$(BITS).o
- extra-y     += init_task.o
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/iommu.c \
                linux-2.6.34.1/arch/sparc/kernel/iommu.c
---- linux-2.6.34.1/arch/sparc/kernel/iommu.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/iommu.c	2010-07-07 09:04:43.000000000 -0400
-@@ -828,7 +828,7 @@ static void dma_4u_sync_sg_for_cpu(struc
- 	spin_unlock_irqrestore(&iommu->lock, flags);
- }
- 
--static struct dma_map_ops sun4u_dma_ops = {
-+static const struct dma_map_ops sun4u_dma_ops = {
- 	.alloc_coherent		= dma_4u_alloc_coherent,
- 	.free_coherent		= dma_4u_free_coherent,
- 	.map_page		= dma_4u_map_page,
-@@ -839,7 +839,7 @@ static struct dma_map_ops sun4u_dma_ops 
- 	.sync_sg_for_cpu	= dma_4u_sync_sg_for_cpu,
- };
- 
--struct dma_map_ops *dma_ops = &sun4u_dma_ops;
-+const struct dma_map_ops *dma_ops = &sun4u_dma_ops;
- EXPORT_SYMBOL(dma_ops);
- 
- extern int pci64_dma_supported(struct pci_dev *pdev, u64 device_mask);
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/ioport.c \
                linux-2.6.34.1/arch/sparc/kernel/ioport.c
---- linux-2.6.34.1/arch/sparc/kernel/ioport.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/ioport.c	2010-07-07 09:04:43.000000000 -0400
-@@ -397,7 +397,7 @@ static void sbus_sync_sg_for_device(stru
- 	BUG();
- }
- 
--struct dma_map_ops sbus_dma_ops = {
-+const struct dma_map_ops sbus_dma_ops = {
- 	.alloc_coherent		= sbus_alloc_coherent,
- 	.free_coherent		= sbus_free_coherent,
- 	.map_page		= sbus_map_page,
-@@ -408,7 +408,7 @@ struct dma_map_ops sbus_dma_ops = {
- 	.sync_sg_for_device	= sbus_sync_sg_for_device,
- };
- 
--struct dma_map_ops *dma_ops = &sbus_dma_ops;
-+const struct dma_map_ops *dma_ops = &sbus_dma_ops;
- EXPORT_SYMBOL(dma_ops);
- 
- static int __init sparc_register_ioport(void)
-@@ -645,7 +645,7 @@ static void pci32_sync_sg_for_device(str
- 	}
- }
- 
--struct dma_map_ops pci32_dma_ops = {
-+const struct dma_map_ops pci32_dma_ops = {
- 	.alloc_coherent		= pci32_alloc_coherent,
- 	.free_coherent		= pci32_free_coherent,
- 	.map_page		= pci32_map_page,
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/kgdb_32.c \
                linux-2.6.34.1/arch/sparc/kernel/kgdb_32.c
---- linux-2.6.34.1/arch/sparc/kernel/kgdb_32.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/kgdb_32.c	2010-07-07 09:04:43.000000000 -0400
-@@ -158,7 +158,7 @@ void kgdb_arch_exit(void)
- {
- }
- 
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- 	/* Breakpoint instruction: ta 0x7d */
- 	.gdb_bpt_instr		= { 0x91, 0xd0, 0x20, 0x7d },
- };
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/kgdb_64.c \
                linux-2.6.34.1/arch/sparc/kernel/kgdb_64.c
---- linux-2.6.34.1/arch/sparc/kernel/kgdb_64.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/kgdb_64.c	2010-07-07 09:04:43.000000000 -0400
-@@ -181,7 +181,7 @@ void kgdb_arch_exit(void)
- {
- }
- 
--struct kgdb_arch arch_kgdb_ops = {
-+const struct kgdb_arch arch_kgdb_ops = {
- 	/* Breakpoint instruction: ta 0x72 */
- 	.gdb_bpt_instr		= { 0x91, 0xd0, 0x20, 0x72 },
- };
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/pci_sun4v.c \
                linux-2.6.34.1/arch/sparc/kernel/pci_sun4v.c
---- linux-2.6.34.1/arch/sparc/kernel/pci_sun4v.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/pci_sun4v.c	2010-07-07 09:04:43.000000000 -0400
-@@ -525,7 +525,7 @@ static void dma_4v_unmap_sg(struct devic
- 	spin_unlock_irqrestore(&iommu->lock, flags);
- }
- 
--static struct dma_map_ops sun4v_dma_ops = {
-+static const struct dma_map_ops sun4v_dma_ops = {
- 	.alloc_coherent			= dma_4v_alloc_coherent,
- 	.free_coherent			= dma_4v_free_coherent,
- 	.map_page			= dma_4v_map_page,
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/sys_sparc_32.c \
                linux-2.6.34.1/arch/sparc/kernel/sys_sparc_32.c
---- linux-2.6.34.1/arch/sparc/kernel/sys_sparc_32.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/sys_sparc_32.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -57,7 +57,7 @@ unsigned long arch_get_unmapped_area(str
- 	if (ARCH_SUN4C && len > 0x20000000)
- 		return -ENOMEM;
- 	if (!addr)
--		addr = TASK_UNMAPPED_BASE;
-+		addr = current->mm->mmap_base;
- 
- 	if (flags & MAP_SHARED)
- 		addr = COLOUR_ALIGN(addr);
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/sys_sparc_64.c \
                linux-2.6.34.1/arch/sparc/kernel/sys_sparc_64.c
---- linux-2.6.34.1/arch/sparc/kernel/sys_sparc_64.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/sys_sparc_64.c	2010-07-07 09:04:43.000000000 \
                -0400
-@@ -124,7 +124,7 @@ unsigned long arch_get_unmapped_area(str
- 		/* We do not accept a shared mapping if it would violate
- 		 * cache aliasing constraints.
- 		 */
--		if ((flags & MAP_SHARED) &&
-+		if ((filp || (flags & MAP_SHARED)) &&
- 		    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
- 			return -EINVAL;
- 		return addr;
-@@ -139,6 +139,10 @@ unsigned long arch_get_unmapped_area(str
- 	if (filp || (flags & MAP_SHARED))
- 		do_color_align = 1;
- 
-+#ifdef CONFIG_PAX_RANDMMAP
-+	if (!(mm->pax_flags & MF_PAX_RANDMMAP))
-+#endif
-+
- 	if (addr) {
- 		if (do_color_align)
- 			addr = COLOUR_ALIGN(addr, pgoff);
-@@ -152,9 +156,9 @@ unsigned long arch_get_unmapped_area(str
- 	}
- 
- 	if (len > mm->cached_hole_size) {
--	        start_addr = addr = mm->free_area_cache;
-+		start_addr = addr = mm->free_area_cache;
- 	} else {
--	        start_addr = addr = TASK_UNMAPPED_BASE;
-+		start_addr = addr = mm->mmap_base;
- 	        mm->cached_hole_size = 0;
- 	}
- 
-@@ -174,8 +178,8 @@ full_search:
- 			vma = find_vma(mm, VA_EXCLUDE_END);
- 		}
- 		if (unlikely(task_size < addr)) {
--			if (start_addr != TASK_UNMAPPED_BASE) {
--				start_addr = addr = TASK_UNMAPPED_BASE;
-+			if (start_addr != mm->mmap_base) {
-+				start_addr = addr = mm->mmap_base;
- 				mm->cached_hole_size = 0;
- 				goto full_search;
- 			}
-@@ -215,7 +219,7 @@ arch_get_unmapped_area_topdown(struct fi
- 		/* We do not accept a shared mapping if it would violate
- 		 * cache aliasing constraints.
- 		 */
--		if ((flags & MAP_SHARED) &&
-+		if ((filp || (flags & MAP_SHARED)) &&
- 		    ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)))
- 			return -EINVAL;
- 		return addr;
-@@ -385,6 +389,12 @@ void arch_pick_mmap_layout(struct mm_str
- 	    gap == RLIM_INFINITY ||
- 	    sysctl_legacy_va_layout) {
- 		mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base += mm->delta_mmap;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area;
- 		mm->unmap_area = arch_unmap_area;
- 	} else {
-@@ -397,6 +407,12 @@ void arch_pick_mmap_layout(struct mm_str
- 			gap = (task_size / 6 * 5);
- 
- 		mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
-+
-+#ifdef CONFIG_PAX_RANDMMAP
-+		if (mm->pax_flags & MF_PAX_RANDMMAP)
-+			mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
-+#endif
-+
- 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
- 		mm->unmap_area = arch_unmap_area_topdown;
- 	}
-diff -urNp linux-2.6.34.1/arch/sparc/kernel/traps_64.c \
                linux-2.6.34.1/arch/sparc/kernel/traps_64.c
---- linux-2.6.34.1/arch/sparc/kernel/traps_64.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/kernel/traps_64.c	2010-07-07 09:04:43.000000000 -0400
-@@ -94,6 +94,12 @@ void bad_trap(struct pt_regs *regs, long
- 
- 	lvl -= 0x100;
- 	if (regs->tstate & TSTATE_PRIV) {
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		if (lvl == 6)
-+			pax_report_refcount_overflow(regs);
-+#endif
-+
- 		sprintf(buffer, "Kernel bad sw trap %lx", lvl);
- 		die_if_kernel(buffer, regs);
- 	}
-@@ -112,11 +118,16 @@ void bad_trap(struct pt_regs *regs, long
- void bad_trap_tl1(struct pt_regs *regs, long lvl)
- {
- 	char buffer[32];
--	
-+
- 	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
- 		       0, lvl, SIGTRAP) == NOTIFY_STOP)
- 		return;
- 
-+#ifdef CONFIG_PAX_REFCOUNT
-+	if (lvl == 6)
-+		pax_report_refcount_overflow(regs);
-+#endif
-+
- 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
- 
- 	sprintf (buffer, "Bad trap %lx at tl>0", lvl);
-diff -urNp linux-2.6.34.1/arch/sparc/lib/atomic_64.S \
                linux-2.6.34.1/arch/sparc/lib/atomic_64.S
---- linux-2.6.34.1/arch/sparc/lib/atomic_64.S	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/lib/atomic_64.S	2010-07-07 09:04:44.000000000 -0400
-@@ -18,7 +18,12 @@
- atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	lduw	[%o1], %g1
--	add	%g1, %o0, %g7
-+	addcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%icc, 2f
-@@ -28,12 +33,32 @@ atomic_add: /* %o0 = increment, %o1 = at
- 2:	BACKOFF_SPIN(%o2, %o3, 1b)
- 	.size	atomic_add, .-atomic_add
- 
-+	.globl	atomic_add_unchecked
-+	.type	atomic_add_unchecked,#function
-+atomic_add_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
-+	BACKOFF_SETUP(%o2)
-+1:	lduw	[%o1], %g1
-+	add	%g1, %o0, %g7
-+	cas	[%o1], %g1, %g7
-+	cmp	%g1, %g7
-+	bne,pn	%icc, 2f
-+	 nop
-+	retl
-+	 nop
-+2:	BACKOFF_SPIN(%o2, %o3, 1b)
-+	.size	atomic_add_unchecked, .-atomic_add_unchecked
-+
- 	.globl	atomic_sub
- 	.type	atomic_sub,#function
- atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	lduw	[%o1], %g1
--	sub	%g1, %o0, %g7
-+	subcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%icc, 2f
-@@ -43,12 +68,32 @@ atomic_sub: /* %o0 = decrement, %o1 = at
- 2:	BACKOFF_SPIN(%o2, %o3, 1b)
- 	.size	atomic_sub, .-atomic_sub
- 
-+	.globl	atomic_sub_unchecked
-+	.type	atomic_sub_unchecked,#function
-+atomic_sub_unchecked: /* %o0 = decrement, %o1 = atomic_ptr */
-+	BACKOFF_SETUP(%o2)
-+1:	lduw	[%o1], %g1
-+	sub	%g1, %o0, %g7
-+	cas	[%o1], %g1, %g7
-+	cmp	%g1, %g7
-+	bne,pn	%icc, 2f
-+	 nop
-+	retl
-+	 nop
-+2:	BACKOFF_SPIN(%o2, %o3, 1b)
-+	.size	atomic_sub_unchecked, .-atomic_sub_unchecked
-+
- 	.globl	atomic_add_ret
- 	.type	atomic_add_ret,#function
- atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	lduw	[%o1], %g1
--	add	%g1, %o0, %g7
-+	addcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%icc, 2f
-@@ -64,7 +109,12 @@ atomic_add_ret: /* %o0 = increment, %o1 
- atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	lduw	[%o1], %g1
--	sub	%g1, %o0, %g7
-+	subcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%icc, 2f
-@@ -80,7 +130,12 @@ atomic_sub_ret: /* %o0 = decrement, %o1 
- atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	ldx	[%o1], %g1
--	add	%g1, %o0, %g7
-+	addcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%xcc, 6
-+#endif
-+
- 	casx	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%xcc, 2f
-@@ -90,12 +145,32 @@ atomic64_add: /* %o0 = increment, %o1 = 
- 2:	BACKOFF_SPIN(%o2, %o3, 1b)
- 	.size	atomic64_add, .-atomic64_add
- 
-+	.globl	atomic64_add_unchecked
-+	.type	atomic64_add_unchecked,#function
-+atomic64_add_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
-+	BACKOFF_SETUP(%o2)
-+1:	ldx	[%o1], %g1
-+	addcc	%g1, %o0, %g7
-+	casx	[%o1], %g1, %g7
-+	cmp	%g1, %g7
-+	bne,pn	%xcc, 2f
-+	 nop
-+	retl
-+	 nop
-+2:	BACKOFF_SPIN(%o2, %o3, 1b)
-+	.size	atomic64_add_unchecked, .-atomic64_add_unchecked
-+
- 	.globl	atomic64_sub
- 	.type	atomic64_sub,#function
- atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	ldx	[%o1], %g1
--	sub	%g1, %o0, %g7
-+	subcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%xcc, 6
-+#endif
-+
- 	casx	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%xcc, 2f
-@@ -105,12 +180,32 @@ atomic64_sub: /* %o0 = decrement, %o1 = 
- 2:	BACKOFF_SPIN(%o2, %o3, 1b)
- 	.size	atomic64_sub, .-atomic64_sub
- 
-+	.globl	atomic64_sub_unchecked
-+	.type	atomic64_sub_unchecked,#function
-+atomic64_sub_unchecked: /* %o0 = decrement, %o1 = atomic_ptr */
-+	BACKOFF_SETUP(%o2)
-+1:	ldx	[%o1], %g1
-+	subcc	%g1, %o0, %g7
-+	casx	[%o1], %g1, %g7
-+	cmp	%g1, %g7
-+	bne,pn	%xcc, 2f
-+	 nop
-+	retl
-+	 nop
-+2:	BACKOFF_SPIN(%o2, %o3, 1b)
-+	.size	atomic64_sub_unchecked, .-atomic64_sub_unchecked
-+
- 	.globl	atomic64_add_ret
- 	.type	atomic64_add_ret,#function
- atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	ldx	[%o1], %g1
--	add	%g1, %o0, %g7
-+	addcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%xcc, 6
-+#endif
-+
- 	casx	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%xcc, 2f
-@@ -121,12 +216,33 @@ atomic64_add_ret: /* %o0 = increment, %o
- 2:	BACKOFF_SPIN(%o2, %o3, 1b)
- 	.size	atomic64_add_ret, .-atomic64_add_ret
- 
-+	.globl	atomic64_add_ret_unchecked
-+	.type	atomic64_add_ret_unchecked,#function
-+atomic64_add_ret_unchecked: /* %o0 = increment, %o1 = atomic_ptr */
-+	BACKOFF_SETUP(%o2)
-+1:	ldx	[%o1], %g1
-+	addcc	%g1, %o0, %g7
-+	casx	[%o1], %g1, %g7
-+	cmp	%g1, %g7
-+	bne,pn	%xcc, 2f
-+	 add	%g7, %o0, %g7
-+	mov	%g7, %o0
-+	retl
-+	 nop
-+2:	BACKOFF_SPIN(%o2, %o3, 1b)
-+	.size	atomic64_add_ret_unchecked, .-atomic64_add_ret_unchecked
-+
- 	.globl	atomic64_sub_ret
- 	.type	atomic64_sub_ret,#function
- atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
- 	BACKOFF_SETUP(%o2)
- 1:	ldx	[%o1], %g1
--	sub	%g1, %o0, %g7
-+	subcc	%g1, %o0, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%xcc, 6
-+#endif
-+
- 	casx	[%o1], %g1, %g7
- 	cmp	%g1, %g7
- 	bne,pn	%xcc, 2f
-diff -urNp linux-2.6.34.1/arch/sparc/lib/ksyms.c \
                linux-2.6.34.1/arch/sparc/lib/ksyms.c
---- linux-2.6.34.1/arch/sparc/lib/ksyms.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/lib/ksyms.c	2010-07-07 09:04:44.000000000 -0400
-@@ -142,12 +142,15 @@ EXPORT_SYMBOL(__downgrade_write);
- 
- /* Atomic counter implementation. */
- EXPORT_SYMBOL(atomic_add);
-+EXPORT_SYMBOL(atomic_add_unchecked);
- EXPORT_SYMBOL(atomic_add_ret);
- EXPORT_SYMBOL(atomic_sub);
-+EXPORT_SYMBOL(atomic_sub_unchecked);
- EXPORT_SYMBOL(atomic_sub_ret);
- EXPORT_SYMBOL(atomic64_add);
- EXPORT_SYMBOL(atomic64_add_ret);
- EXPORT_SYMBOL(atomic64_sub);
-+EXPORT_SYMBOL(atomic64_sub_unchecked);
- EXPORT_SYMBOL(atomic64_sub_ret);
- 
- /* Atomic bit operations. */
-diff -urNp linux-2.6.34.1/arch/sparc/lib/rwsem_64.S \
                linux-2.6.34.1/arch/sparc/lib/rwsem_64.S
---- linux-2.6.34.1/arch/sparc/lib/rwsem_64.S	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/lib/rwsem_64.S	2010-07-07 09:04:44.000000000 -0400
-@@ -11,7 +11,12 @@
- 	.globl		__down_read
- __down_read:
- 1:	lduw		[%o0], %g1
--	add		%g1, 1, %g7
-+	addcc		%g1, 1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g1, %g7
- 	cmp		%g1, %g7
- 	bne,pn		%icc, 1b
-@@ -33,7 +38,12 @@ __down_read:
- 	.globl		__down_read_trylock
- __down_read_trylock:
- 1:	lduw		[%o0], %g1
--	add		%g1, 1, %g7
-+	addcc		%g1, 1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cmp		%g7, 0
- 	bl,pn		%icc, 2f
- 	 mov		0, %o1
-@@ -51,7 +61,12 @@ __down_write:
- 	or		%g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
- 1:
- 	lduw		[%o0], %g3
--	add		%g3, %g1, %g7
-+	addcc		%g3, %g1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g3, %g7
- 	cmp		%g3, %g7
- 	bne,pn		%icc, 1b
-@@ -77,7 +92,12 @@ __down_write_trylock:
- 	cmp		%g3, 0
- 	bne,pn		%icc, 2f
- 	 mov		0, %o1
--	add		%g3, %g1, %g7
-+	addcc		%g3, %g1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g3, %g7
- 	cmp		%g3, %g7
- 	bne,pn		%icc, 1b
-@@ -90,7 +110,12 @@ __down_write_trylock:
- __up_read:
- 1:
- 	lduw		[%o0], %g1
--	sub		%g1, 1, %g7
-+	subcc		%g1, 1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g1, %g7
- 	cmp		%g1, %g7
- 	bne,pn		%icc, 1b
-@@ -118,7 +143,12 @@ __up_write:
- 	or		%g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
- 1:
- 	lduw		[%o0], %g3
--	sub		%g3, %g1, %g7
-+	subcc		%g3, %g1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g3, %g7
- 	cmp		%g3, %g7
- 	bne,pn		%icc, 1b
-@@ -143,7 +173,12 @@ __downgrade_write:
- 	or		%g1, %lo(RWSEM_WAITING_BIAS), %g1
- 1:
- 	lduw		[%o0], %g3
--	sub		%g3, %g1, %g7
-+	subcc		%g3, %g1, %g7
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+	tvs	%icc, 6
-+#endif
-+
- 	cas		[%o0], %g3, %g7
- 	cmp		%g3, %g7
- 	bne,pn		%icc, 1b
-diff -urNp linux-2.6.34.1/arch/sparc/mm/Makefile \
                linux-2.6.34.1/arch/sparc/mm/Makefile
---- linux-2.6.34.1/arch/sparc/mm/Makefile	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/mm/Makefile	2010-07-07 09:04:44.000000000 -0400
-@@ -2,7 +2,7 @@
- #
- 
- asflags-y := -ansi
--ccflags-y := -Werror
-+#ccflags-y := -Werror
- 
- obj-$(CONFIG_SPARC64)   += ultra.o tlb.o tsb.o
- obj-y                   += fault_$(BITS).o
-diff -urNp linux-2.6.34.1/arch/sparc/mm/fault_32.c \
                linux-2.6.34.1/arch/sparc/mm/fault_32.c
---- linux-2.6.34.1/arch/sparc/mm/fault_32.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/mm/fault_32.c	2010-07-07 09:04:44.000000000 -0400
-@@ -22,6 +22,9 @@
- #include <linux/interrupt.h>
- #include <linux/module.h>
- #include <linux/kdebug.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/compiler.h>
- 
- #include <asm/system.h>
- #include <asm/page.h>
-@@ -209,6 +212,268 @@ static unsigned long compute_si_addr(str
- 	return safe_compute_effective_address(regs, insn);
- }
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+#ifdef CONFIG_PAX_DLRESOLVE
-+static void pax_emuplt_close(struct vm_area_struct *vma)
-+{
-+	vma->vm_mm->call_dl_resolve = 0UL;
-+}
-+
-+static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+	unsigned int *kaddr;
-+
-+	vmf->page = alloc_page(GFP_HIGHUSER);
-+	if (!vmf->page)
-+		return VM_FAULT_OOM;
-+
-+	kaddr = kmap(vmf->page);
-+	memset(kaddr, 0, PAGE_SIZE);
-+	kaddr[0] = 0x9DE3BFA8U; /* save */
-+	flush_dcache_page(vmf->page);
-+	kunmap(vmf->page);
-+	return VM_FAULT_MAJOR;
-+}
-+
-+static const struct vm_operations_struct pax_vm_ops = {
-+	.close = pax_emuplt_close,
-+	.fault = pax_emuplt_fault
-+};
-+
-+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
-+{
-+	int ret;
-+
-+	INIT_LIST_HEAD(&vma->anon_vma_chain);
-+	vma->vm_mm = current->mm;
-+	vma->vm_start = addr;
-+	vma->vm_end = addr + PAGE_SIZE;
-+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
-+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-+	vma->vm_ops = &pax_vm_ops;
-+
-+	ret = insert_vm_struct(current->mm, vma);
-+	if (ret)
-+		return ret;
-+
-+	++current->mm->total_vm;
-+	return 0;
-+}
-+#endif
-+
-+/*
-+ * PaX: decide what to do with offenders (regs->pc = fault address)
-+ *
-+ * returns 1 when task should be killed
-+ *         2 when patched PLT trampoline was detected
-+ *         3 when unpatched PLT trampoline was detected
-+ */
-+static int pax_handle_fetch_fault(struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+	int err;
-+
-+	do { /* PaX: patched PLT emulation #1 */
-+		unsigned int sethi1, sethi2, jmpl;
-+
-+		err = get_user(sethi1, (unsigned int *)regs->pc);
-+		err |= get_user(sethi2, (unsigned int *)(regs->pc+4));
-+		err |= get_user(jmpl, (unsigned int *)(regs->pc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi2 & 0xFFC00000U) == 0x03000000U &&
-+		    (jmpl & 0xFFFFE000U) == 0x81C06000U)
-+		{
-+			unsigned int addr;
-+
-+			regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
-+			addr = regs->u_regs[UREG_G1];
-+			addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
-+			regs->pc = addr;
-+			regs->npc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	{ /* PaX: patched PLT emulation #2 */
-+		unsigned int ba;
-+
-+		err = get_user(ba, (unsigned int *)regs->pc);
-+
-+		if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
-+			unsigned int addr;
-+
-+			addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
-+			regs->pc = addr;
-+			regs->npc = addr+4;
-+			return 2;
-+		}
-+	}
-+
-+	do { /* PaX: patched PLT emulation #3 */
-+		unsigned int sethi, jmpl, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->pc);
-+		err |= get_user(jmpl, (unsigned int *)(regs->pc+4));
-+		err |= get_user(nop, (unsigned int *)(regs->pc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    (jmpl & 0xFFFFE000U) == 0x81C06000U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned int addr;
-+
-+			addr = (sethi & 0x003FFFFFU) << 10;
-+			regs->u_regs[UREG_G1] = addr;
-+			addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
-+			regs->pc = addr;
-+			regs->npc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: unpatched PLT emulation step 1 */
-+		unsigned int sethi, ba, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->pc);
-+		err |= get_user(ba, (unsigned int *)(regs->pc+4));
-+		err |= get_user(nop, (unsigned int *)(regs->pc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned int addr, save, call;
-+
-+			if ((ba & 0xFFC00000U) == 0x30800000U)
-+				addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << \
                2);
-+			else
-+				addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << \
                2);
-+
-+			err = get_user(save, (unsigned int *)addr);
-+			err |= get_user(call, (unsigned int *)(addr+4));
-+			err |= get_user(nop, (unsigned int *)(addr+8));
-+			if (err)
-+				break;
-+
-+#ifdef CONFIG_PAX_DLRESOLVE
-+			if (save == 0x9DE3BFA8U &&
-+			    (call & 0xC0000000U) == 0x40000000U &&
-+			    nop == 0x01000000U)
-+			{
-+				struct vm_area_struct *vma;
-+				unsigned long call_dl_resolve;
-+
-+				down_read(&current->mm->mmap_sem);
-+				call_dl_resolve = current->mm->call_dl_resolve;
-+				up_read(&current->mm->mmap_sem);
-+				if (likely(call_dl_resolve))
-+					goto emulate;
-+
-+				vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
-+
-+				down_write(&current->mm->mmap_sem);
-+				if (current->mm->call_dl_resolve) {
-+					call_dl_resolve = current->mm->call_dl_resolve;
-+					up_write(&current->mm->mmap_sem);
-+					if (vma)
-+						kmem_cache_free(vm_area_cachep, vma);
-+					goto emulate;
-+				}
-+
-+				call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
-+				if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
-+					up_write(&current->mm->mmap_sem);
-+					if (vma)
-+						kmem_cache_free(vm_area_cachep, vma);
-+					return 1;
-+				}
-+
-+				if (pax_insert_vma(vma, call_dl_resolve)) {
-+					up_write(&current->mm->mmap_sem);
-+					kmem_cache_free(vm_area_cachep, vma);
-+					return 1;
-+				}
-+
-+				current->mm->call_dl_resolve = call_dl_resolve;
-+				up_write(&current->mm->mmap_sem);
-+
-+emulate:
-+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
-+				regs->pc = call_dl_resolve;
-+				regs->npc = addr+4;
-+				return 3;
-+			}
-+#endif
-+
-+			/* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */
-+			if ((save & 0xFFC00000U) == 0x05000000U &&
-+			    (call & 0xFFFFE000U) == 0x85C0A000U &&
-+			    nop == 0x01000000U)
-+			{
-+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
-+				regs->u_regs[UREG_G2] = addr + 4;
-+				addr = (save & 0x003FFFFFU) << 10;
-+				addr += (((call | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
-+				regs->pc = addr;
-+				regs->npc = addr+4;
-+				return 3;
-+			}
-+		}
-+	} while (0);
-+
-+	do { /* PaX: unpatched PLT emulation step 2 */
-+		unsigned int save, call, nop;
-+
-+		err = get_user(save, (unsigned int *)(regs->pc-4));
-+		err |= get_user(call, (unsigned int *)regs->pc);
-+		err |= get_user(nop, (unsigned int *)(regs->pc+4));
-+		if (err)
-+			break;
-+
-+		if (save == 0x9DE3BFA8U &&
-+		    (call & 0xC0000000U) == 0x40000000U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + \
                0x20000000U) << 2);
-+
-+			regs->u_regs[UREG_RETPC] = regs->pc;
-+			regs->pc = dl_resolve;
-+			regs->npc = dl_resolve+4;
-+			return 3;
-+		}
-+	} while (0);
-+#endif
-+
-+	return 1;
-+}
-+
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 8; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
- 				      int text_fault)
- {
-@@ -282,6 +547,24 @@ good_area:
- 		if(!(vma->vm_flags & VM_WRITE))
- 			goto bad_area;
- 	} else {
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+		if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & \
                VM_EXEC)) {
-+			up_read(&mm->mmap_sem);
-+			switch (pax_handle_fetch_fault(regs)) {
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+			case 2:
-+			case 3:
-+				return;
-+#endif
-+
-+			}
-+			pax_report_fault(regs, (void *)regs->pc, (void *)regs->u_regs[UREG_FP]);
-+			do_group_exit(SIGKILL);
-+		}
-+#endif
-+
- 		/* Allow reads even for write-only mappings */
- 		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
- 			goto bad_area;
-diff -urNp linux-2.6.34.1/arch/sparc/mm/fault_64.c \
                linux-2.6.34.1/arch/sparc/mm/fault_64.c
---- linux-2.6.34.1/arch/sparc/mm/fault_64.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/mm/fault_64.c	2010-07-07 09:04:44.000000000 -0400
-@@ -21,6 +21,9 @@
- #include <linux/kprobes.h>
- #include <linux/kdebug.h>
- #include <linux/percpu.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/compiler.h>
- 
- #include <asm/page.h>
- #include <asm/pgtable.h>
-@@ -272,6 +275,457 @@ static void noinline __kprobes bogus_32b
- 	show_regs(regs);
- }
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+#ifdef CONFIG_PAX_DLRESOLVE
-+static void pax_emuplt_close(struct vm_area_struct *vma)
-+{
-+	vma->vm_mm->call_dl_resolve = 0UL;
-+}
-+
-+static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-+{
-+	unsigned int *kaddr;
-+
-+	vmf->page = alloc_page(GFP_HIGHUSER);
-+	if (!vmf->page)
-+		return VM_FAULT_OOM;
-+
-+	kaddr = kmap(vmf->page);
-+	memset(kaddr, 0, PAGE_SIZE);
-+	kaddr[0] = 0x9DE3BFA8U; /* save */
-+	flush_dcache_page(vmf->page);
-+	kunmap(vmf->page);
-+	return VM_FAULT_MAJOR;
-+}
-+
-+static const struct vm_operations_struct pax_vm_ops = {
-+	.close = pax_emuplt_close,
-+	.fault = pax_emuplt_fault
-+};
-+
-+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
-+{
-+	int ret;
-+
-+	INIT_LIST_HEAD(&vma->anon_vma_chain);
-+	vma->vm_mm = current->mm;
-+	vma->vm_start = addr;
-+	vma->vm_end = addr + PAGE_SIZE;
-+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
-+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-+	vma->vm_ops = &pax_vm_ops;
-+
-+	ret = insert_vm_struct(current->mm, vma);
-+	if (ret)
-+		return ret;
-+
-+	++current->mm->total_vm;
-+	return 0;
-+}
-+#endif
-+
-+/*
-+ * PaX: decide what to do with offenders (regs->tpc = fault address)
-+ *
-+ * returns 1 when task should be killed
-+ *         2 when patched PLT trampoline was detected
-+ *         3 when unpatched PLT trampoline was detected
-+ */
-+static int pax_handle_fetch_fault(struct pt_regs *regs)
-+{
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+	int err;
-+
-+	do { /* PaX: patched PLT emulation #1 */
-+		unsigned int sethi1, sethi2, jmpl;
-+
-+		err = get_user(sethi1, (unsigned int *)regs->tpc);
-+		err |= get_user(sethi2, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(jmpl, (unsigned int *)(regs->tpc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi2 & 0xFFC00000U) == 0x03000000U &&
-+		    (jmpl & 0xFFFFE000U) == 0x81C06000U)
-+		{
-+			unsigned long addr;
-+
-+			regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
-+			addr = regs->u_regs[UREG_G1];
-+			addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	{ /* PaX: patched PLT emulation #2 */
-+		unsigned int ba;
-+
-+		err = get_user(ba, (unsigned int *)regs->tpc);
-+
-+		if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
-+			unsigned long addr;
-+
-+			addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + \
                0x00200000UL) << 2);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	}
-+
-+	do { /* PaX: patched PLT emulation #3 */
-+		unsigned int sethi, jmpl, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(jmpl, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    (jmpl & 0xFFFFE000U) == 0x81C06000U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long addr;
-+
-+			addr = (sethi & 0x003FFFFFU) << 10;
-+			regs->u_regs[UREG_G1] = addr;
-+			addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: patched PLT emulation #4 */
-+		unsigned int sethi, mov1, call, mov2;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(mov1, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(call, (unsigned int *)(regs->tpc+8));
-+		err |= get_user(mov2, (unsigned int *)(regs->tpc+12));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    mov1 == 0x8210000FU &&
-+		    (call & 0xC0000000U) == 0x40000000U &&
-+		    mov2 == 0x9E100001U)
-+		{
-+			unsigned long addr;
-+
-+			regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
-+			addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + \
                0x20000000UL) << 2);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: patched PLT emulation #5 */
-+		unsigned int sethi, sethi1, sethi2, or1, or2, sllx, jmpl, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(sethi1, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(sethi2, (unsigned int *)(regs->tpc+8));
-+		err |= get_user(or1, (unsigned int *)(regs->tpc+12));
-+		err |= get_user(or2, (unsigned int *)(regs->tpc+16));
-+		err |= get_user(sllx, (unsigned int *)(regs->tpc+20));
-+		err |= get_user(jmpl, (unsigned int *)(regs->tpc+24));
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+28));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi1 & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi2 & 0xFFC00000U) == 0x0B000000U &&
-+		    (or1 & 0xFFFFE000U) == 0x82106000U &&
-+		    (or2 & 0xFFFFE000U) == 0x8A116000U &&
-+		    sllx == 0x83287020U &&
-+		    jmpl == 0x81C04005U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long addr;
-+
-+			regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
-+			regs->u_regs[UREG_G1] <<= 32;
-+			regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
-+			addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: patched PLT emulation #6 */
-+		unsigned int sethi, sethi1, sethi2, sllx, or,  jmpl, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(sethi1, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(sethi2, (unsigned int *)(regs->tpc+8));
-+		err |= get_user(sllx, (unsigned int *)(regs->tpc+12));
-+		err |= get_user(or, (unsigned int *)(regs->tpc+16));
-+		err |= get_user(jmpl, (unsigned int *)(regs->tpc+20));
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+24));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi1 & 0xFFC00000U) == 0x03000000U &&
-+		    (sethi2 & 0xFFC00000U) == 0x0B000000U &&
-+		    sllx == 0x83287020U &&
-+		    (or & 0xFFFFE000U) == 0x8A116000U &&
-+		    jmpl == 0x81C04005U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long addr;
-+
-+			regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
-+			regs->u_regs[UREG_G1] <<= 32;
-+			regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
-+			addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+	do { /* PaX: unpatched PLT emulation step 1 */
-+		unsigned int sethi, ba, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(ba, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long addr;
-+			unsigned int save, call;
-+			unsigned int sethi1, sethi2, or1, or2, sllx, add, jmpl;
-+
-+			if ((ba & 0xFFC00000U) == 0x30800000U)
-+				addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + \
                0x00200000UL) << 2);
-+			else
-+				addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + \
                0x00040000UL) << 2);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			err = get_user(save, (unsigned int *)addr);
-+			err |= get_user(call, (unsigned int *)(addr+4));
-+			err |= get_user(nop, (unsigned int *)(addr+8));
-+			if (err)
-+				break;
-+
-+#ifdef CONFIG_PAX_DLRESOLVE
-+			if (save == 0x9DE3BFA8U &&
-+			    (call & 0xC0000000U) == 0x40000000U &&
-+			    nop == 0x01000000U)
-+			{
-+				struct vm_area_struct *vma;
-+				unsigned long call_dl_resolve;
-+
-+				down_read(&current->mm->mmap_sem);
-+				call_dl_resolve = current->mm->call_dl_resolve;
-+				up_read(&current->mm->mmap_sem);
-+				if (likely(call_dl_resolve))
-+					goto emulate;
-+
-+				vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
-+
-+				down_write(&current->mm->mmap_sem);
-+				if (current->mm->call_dl_resolve) {
-+					call_dl_resolve = current->mm->call_dl_resolve;
-+					up_write(&current->mm->mmap_sem);
-+					if (vma)
-+						kmem_cache_free(vm_area_cachep, vma);
-+					goto emulate;
-+				}
-+
-+				call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
-+				if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
-+					up_write(&current->mm->mmap_sem);
-+					if (vma)
-+						kmem_cache_free(vm_area_cachep, vma);
-+					return 1;
-+				}
-+
-+				if (pax_insert_vma(vma, call_dl_resolve)) {
-+					up_write(&current->mm->mmap_sem);
-+					kmem_cache_free(vm_area_cachep, vma);
-+					return 1;
-+				}
-+
-+				current->mm->call_dl_resolve = call_dl_resolve;
-+				up_write(&current->mm->mmap_sem);
-+
-+emulate:
-+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
-+				regs->tpc = call_dl_resolve;
-+				regs->tnpc = addr+4;
-+				return 3;
-+			}
-+#endif
-+
-+			/* PaX: glibc 2.4+ generates sethi/jmpl instead of save/call */
-+			if ((save & 0xFFC00000U) == 0x05000000U &&
-+			    (call & 0xFFFFE000U) == 0x85C0A000U &&
-+			    nop == 0x01000000U)
-+			{
-+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
-+				regs->u_regs[UREG_G2] = addr + 4;
-+				addr = (save & 0x003FFFFFU) << 10;
-+				addr += (((call | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
-+
-+				if (test_thread_flag(TIF_32BIT))
-+					addr &= 0xFFFFFFFFUL;
-+
-+				regs->tpc = addr;
-+				regs->tnpc = addr+4;
-+				return 3;
-+			}
-+
-+			/* PaX: 64-bit PLT stub */
-+			err = get_user(sethi1, (unsigned int *)addr);
-+			err |= get_user(sethi2, (unsigned int *)(addr+4));
-+			err |= get_user(or1, (unsigned int *)(addr+8));
-+			err |= get_user(or2, (unsigned int *)(addr+12));
-+			err |= get_user(sllx, (unsigned int *)(addr+16));
-+			err |= get_user(add, (unsigned int *)(addr+20));
-+			err |= get_user(jmpl, (unsigned int *)(addr+24));
-+			err |= get_user(nop, (unsigned int *)(addr+28));
-+			if (err)
-+				break;
-+
-+			if ((sethi1 & 0xFFC00000U) == 0x09000000U &&
-+			    (sethi2 & 0xFFC00000U) == 0x0B000000U &&
-+			    (or1 & 0xFFFFE000U) == 0x88112000U &&
-+			    (or2 & 0xFFFFE000U) == 0x8A116000U &&
-+			    sllx == 0x89293020U &&
-+			    add == 0x8A010005U &&
-+			    jmpl == 0x89C14000U &&
-+			    nop == 0x01000000U)
-+			{
-+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
-+				regs->u_regs[UREG_G4] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
-+				regs->u_regs[UREG_G4] <<= 32;
-+				regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
-+				regs->u_regs[UREG_G5] += regs->u_regs[UREG_G4];
-+				regs->u_regs[UREG_G4] = addr + 24;
-+				addr = regs->u_regs[UREG_G5];
-+				regs->tpc = addr;
-+				regs->tnpc = addr+4;
-+				return 3;
-+			}
-+		}
-+	} while (0);
-+
-+#ifdef CONFIG_PAX_DLRESOLVE
-+	do { /* PaX: unpatched PLT emulation step 2 */
-+		unsigned int save, call, nop;
-+
-+		err = get_user(save, (unsigned int *)(regs->tpc-4));
-+		err |= get_user(call, (unsigned int *)regs->tpc);
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+4));
-+		if (err)
-+			break;
-+
-+		if (save == 0x9DE3BFA8U &&
-+		    (call & 0xC0000000U) == 0x40000000U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ \
                0x20000000UL) + 0x20000000UL) << 2);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				dl_resolve &= 0xFFFFFFFFUL;
-+
-+			regs->u_regs[UREG_RETPC] = regs->tpc;
-+			regs->tpc = dl_resolve;
-+			regs->tnpc = dl_resolve+4;
-+			return 3;
-+		}
-+	} while (0);
-+#endif
-+
-+	do { /* PaX: patched PLT emulation #7, must be AFTER the unpatched PLT emulation \
                */
-+		unsigned int sethi, ba, nop;
-+
-+		err = get_user(sethi, (unsigned int *)regs->tpc);
-+		err |= get_user(ba, (unsigned int *)(regs->tpc+4));
-+		err |= get_user(nop, (unsigned int *)(regs->tpc+8));
-+
-+		if (err)
-+			break;
-+
-+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
-+		    (ba & 0xFFF00000U) == 0x30600000U &&
-+		    nop == 0x01000000U)
-+		{
-+			unsigned long addr;
-+
-+			addr = (sethi & 0x003FFFFFU) << 10;
-+			regs->u_regs[UREG_G1] = addr;
-+			addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + \
                0x00040000UL) << 2);
-+
-+			if (test_thread_flag(TIF_32BIT))
-+				addr &= 0xFFFFFFFFUL;
-+
-+			regs->tpc = addr;
-+			regs->tnpc = addr+4;
-+			return 2;
-+		}
-+	} while (0);
-+
-+#endif
-+
-+	return 1;
-+}
-+
-+void pax_report_insns(void *pc, void *sp)
-+{
-+	unsigned long i;
-+
-+	printk(KERN_ERR "PAX: bytes at PC: ");
-+	for (i = 0; i < 8; i++) {
-+		unsigned int c;
-+		if (get_user(c, (unsigned int *)pc+i))
-+			printk(KERN_CONT "???????? ");
-+		else
-+			printk(KERN_CONT "%08x ", c);
-+	}
-+	printk("\n");
-+}
-+#endif
-+
- asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
- {
- 	struct mm_struct *mm = current->mm;
-@@ -340,6 +794,29 @@ asmlinkage void __kprobes do_sparc64_fau
- 	if (!vma)
- 		goto bad_area;
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+	/* PaX: detect ITLB misses on non-exec pages */
-+	if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address &&
-+	    !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
-+	{
-+		if (address != regs->tpc)
-+			goto good_area;
-+
-+		up_read(&mm->mmap_sem);
-+		switch (pax_handle_fetch_fault(regs)) {
-+
-+#ifdef CONFIG_PAX_EMUPLT
-+		case 2:
-+		case 3:
-+			return;
-+#endif
-+
-+		}
-+		pax_report_fault(regs, (void *)regs->tpc, (void *)(regs->u_regs[UREG_FP] + \
                STACK_BIAS));
-+		do_group_exit(SIGKILL);
-+	}
-+#endif
-+
- 	/* Pure DTLB misses do not tell us whether the fault causing
- 	 * load/store/atomic was a write or not, it only says that there
- 	 * was no match.  So in such a case we (carefully) read the
-diff -urNp linux-2.6.34.1/arch/sparc/mm/init_32.c \
                linux-2.6.34.1/arch/sparc/mm/init_32.c
---- linux-2.6.34.1/arch/sparc/mm/init_32.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/mm/init_32.c	2010-07-07 09:04:44.000000000 -0400
-@@ -318,6 +318,9 @@ extern void device_scan(void);
- pgprot_t PAGE_SHARED __read_mostly;
- EXPORT_SYMBOL(PAGE_SHARED);
- 
-+pgprot_t PAGE_SHARED_NOEXEC __read_mostly;
-+EXPORT_SYMBOL(PAGE_SHARED_NOEXEC);
-+
- void __init paging_init(void)
- {
- 	switch(sparc_cpu_model) {
-@@ -346,17 +349,17 @@ void __init paging_init(void)
- 
- 	/* Initialize the protection map with non-constant, MMU dependent values. */
- 	protection_map[0] = PAGE_NONE;
--	protection_map[1] = PAGE_READONLY;
--	protection_map[2] = PAGE_COPY;
--	protection_map[3] = PAGE_COPY;
-+	protection_map[1] = PAGE_READONLY_NOEXEC;
-+	protection_map[2] = PAGE_COPY_NOEXEC;
-+	protection_map[3] = PAGE_COPY_NOEXEC;
- 	protection_map[4] = PAGE_READONLY;
- 	protection_map[5] = PAGE_READONLY;
- 	protection_map[6] = PAGE_COPY;
- 	protection_map[7] = PAGE_COPY;
- 	protection_map[8] = PAGE_NONE;
--	protection_map[9] = PAGE_READONLY;
--	protection_map[10] = PAGE_SHARED;
--	protection_map[11] = PAGE_SHARED;
-+	protection_map[9] = PAGE_READONLY_NOEXEC;
-+	protection_map[10] = PAGE_SHARED_NOEXEC;
-+	protection_map[11] = PAGE_SHARED_NOEXEC;
- 	protection_map[12] = PAGE_READONLY;
- 	protection_map[13] = PAGE_READONLY;
- 	protection_map[14] = PAGE_SHARED;
-diff -urNp linux-2.6.34.1/arch/sparc/mm/srmmu.c linux-2.6.34.1/arch/sparc/mm/srmmu.c
---- linux-2.6.34.1/arch/sparc/mm/srmmu.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/sparc/mm/srmmu.c	2010-07-07 09:04:44.000000000 -0400
-@@ -2198,6 +2198,13 @@ void __init ld_mmu_srmmu(void)
- 	PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED);
- 	BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
- 	BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
-+
-+#ifdef CONFIG_PAX_PAGEEXEC
-+	PAGE_SHARED_NOEXEC = pgprot_val(SRMMU_PAGE_SHARED_NOEXEC);
-+	BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
-+	BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
-+#endif
-+
- 	BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
- 	page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
- 
-diff -urNp linux-2.6.34.1/arch/um/include/asm/kmap_types.h \
                linux-2.6.34.1/arch/um/include/asm/kmap_types.h
---- linux-2.6.34.1/arch/um/include/asm/kmap_types.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/um/include/asm/kmap_types.h	2010-07-07 09:04:44.000000000 \
                -0400
-@@ -23,6 +23,7 @@ enum km_type {
- 	KM_IRQ1,
- 	KM_SOFTIRQ0,
- 	KM_SOFTIRQ1,
-+	KM_CLEARPAGE,
- 	KM_TYPE_NR
- };
- 
-diff -urNp linux-2.6.34.1/arch/um/include/asm/page.h \
                linux-2.6.34.1/arch/um/include/asm/page.h
---- linux-2.6.34.1/arch/um/include/asm/page.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/um/include/asm/page.h	2010-07-07 09:04:44.000000000 -0400
-@@ -14,6 +14,9 @@
- #define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
- #define PAGE_MASK	(~(PAGE_SIZE-1))
- 
-+#define ktla_ktva(addr)			(addr)
-+#define ktva_ktla(addr)			(addr)
-+
- #ifndef __ASSEMBLY__
- 
- struct page;
-diff -urNp linux-2.6.34.1/arch/um/sys-i386/syscalls.c \
                linux-2.6.34.1/arch/um/sys-i386/syscalls.c
---- linux-2.6.34.1/arch/um/sys-i386/syscalls.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/um/sys-i386/syscalls.c	2010-07-07 09:04:44.000000000 -0400
-@@ -11,6 +11,21 @@
- #include "asm/uaccess.h"
- #include "asm/unistd.h"
- 
-+int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
-+{
-+	unsigned long pax_task_size = TASK_SIZE;
-+
-+#ifdef CONFIG_PAX_SEGMEXEC
-+	if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
-+		pax_task_size = SEGMEXEC_TASK_SIZE;
-+#endif
-+
-+	if (len > pax_task_size || addr > pax_task_size - len)
-+		return -EINVAL;
-+
-+	return 0;
-+}
-+
- /*
-  * The prototype on i386 is:
-  *
-diff -urNp linux-2.6.34.1/arch/x86/Kconfig linux-2.6.34.1/arch/x86/Kconfig
---- linux-2.6.34.1/arch/x86/Kconfig	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/Kconfig	2010-07-07 09:04:46.000000000 -0400
-@@ -1123,7 +1123,7 @@ config PAGE_OFFSET
- 	hex
- 	default 0xB0000000 if VMSPLIT_3G_OPT
- 	default 0x80000000 if VMSPLIT_2G
--	default 0x78000000 if VMSPLIT_2G_OPT
-+	default 0x70000000 if VMSPLIT_2G_OPT
- 	default 0x40000000 if VMSPLIT_1G
- 	default 0xC0000000
- 	depends on X86_32
-@@ -1457,7 +1457,7 @@ config ARCH_USES_PG_UNCACHED
- 
- config EFI
- 	bool "EFI runtime service support"
--	depends on ACPI
-+	depends on ACPI && !PAX_KERNEXEC
- 	---help---
- 	  This enables the kernel to use EFI runtime services that are
- 	  available (such as the EFI variable services).
-@@ -1544,6 +1544,7 @@ config KEXEC_JUMP
- config PHYSICAL_START
- 	hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
- 	default "0x1000000"
-+	range 0x400000 0x40000000
- 	---help---
- 	  This gives the physical address where the kernel is loaded.
- 
-@@ -1608,6 +1609,7 @@ config PHYSICAL_ALIGN
- 	hex
- 	prompt "Alignment value to which kernel should be aligned" if X86_32
- 	default "0x1000000"
-+	range 0x400000 0x1000000 if PAX_KERNEXEC
- 	range 0x2000 0x1000000
- 	---help---
- 	  This value puts the alignment restrictions on physical address
-@@ -1639,9 +1641,10 @@ config HOTPLUG_CPU
- 	  Say N if you want to disable CPU hotplug.
- 
- config COMPAT_VDSO
--	def_bool y
-+	def_bool n
- 	prompt "Compat VDSO support"
- 	depends on X86_32 || IA32_EMULATION
-+	depends on !PAX_NOEXEC && !PAX_MEMORY_UDEREF
- 	---help---
- 	  Map the 32-bit VDSO to the predictable old-style address too.
- 
-diff -urNp linux-2.6.34.1/arch/x86/Kconfig.cpu linux-2.6.34.1/arch/x86/Kconfig.cpu
---- linux-2.6.34.1/arch/x86/Kconfig.cpu	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/Kconfig.cpu	2010-07-07 09:04:46.000000000 -0400
-@@ -336,7 +336,7 @@ config X86_PPRO_FENCE
- 
- config X86_F00F_BUG
- 	def_bool y
--	depends on M586MMX || M586TSC || M586 || M486 || M386
-+	depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
- 
- config X86_WP_WORKS_OK
- 	def_bool y
-@@ -356,7 +356,7 @@ config X86_POPAD_OK
- 
- config X86_ALIGNMENT_16
- 	def_bool y
--	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || \
                M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
-+	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 \
|| MCORE2 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || \
                M586 || M486 || MVIAC3_2 || MGEODEGX1
- 
- config X86_INTEL_USERCOPY
- 	def_bool y
-@@ -402,7 +402,7 @@ config X86_CMPXCHG64
- # generates cmov.
- config X86_CMOV
- 	def_bool y
--	depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || \
MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM \
                || MGEODE_LX)
-+	depends on (MK8 || MK7 || MCORE2 || MPSC || MPENTIUM4 || MPENTIUMM || MPENTIUMIII \
|| MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || \
                MATOM || MGEODE_LX)
- 
- config X86_MINIMUM_CPU_FAMILY
- 	int
-diff -urNp linux-2.6.34.1/arch/x86/Kconfig.debug \
                linux-2.6.34.1/arch/x86/Kconfig.debug
---- linux-2.6.34.1/arch/x86/Kconfig.debug	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/Kconfig.debug	2010-07-07 09:04:46.000000000 -0400
-@@ -99,7 +99,7 @@ config X86_PTDUMP
- config DEBUG_RODATA
- 	bool "Write protect kernel read-only data structures"
- 	default y
--	depends on DEBUG_KERNEL
-+	depends on DEBUG_KERNEL && BROKEN
- 	---help---
- 	  Mark the kernel read-only data as write-protected in the pagetables,
- 	  in order to catch accidental (and incorrect) writes to such const
-diff -urNp linux-2.6.34.1/arch/x86/Makefile linux-2.6.34.1/arch/x86/Makefile
---- linux-2.6.34.1/arch/x86/Makefile	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/Makefile	2010-07-07 09:04:49.000000000 -0400
-@@ -190,3 +190,12 @@ define archhelp
-   echo  '                  FDARGS="..."  arguments for the booted kernel'
-   echo  '                  FDINITRD=file initrd for the booted kernel'
- endef
-+
-+define OLD_LD
-+
-+*** ${VERSION}.${PATCHLEVEL} PaX kernels no longer build correctly with old \
                versions of binutils.
-+*** Please upgrade your binutils to 2.18 or newer
-+endef
-+
-+archprepare:
-+	$(if $(LDFLAGS_BUILD_ID),,$(error $(OLD_LD)))
-diff -urNp linux-2.6.34.1/arch/x86/boot/bitops.h \
                linux-2.6.34.1/arch/x86/boot/bitops.h
---- linux-2.6.34.1/arch/x86/boot/bitops.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/bitops.h	2010-07-07 09:04:44.000000000 -0400
-@@ -26,7 +26,7 @@ static inline int variable_test_bit(int 
- 	u8 v;
- 	const u32 *p = (const u32 *)addr;
- 
--	asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
-+	asm volatile("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
- 	return v;
- }
- 
-@@ -37,7 +37,7 @@ static inline int variable_test_bit(int 
- 
- static inline void set_bit(int nr, void *addr)
- {
--	asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
-+	asm volatile("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
- }
- 
- #endif /* BOOT_BITOPS_H */
-diff -urNp linux-2.6.34.1/arch/x86/boot/boot.h linux-2.6.34.1/arch/x86/boot/boot.h
---- linux-2.6.34.1/arch/x86/boot/boot.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/boot.h	2010-07-07 09:04:44.000000000 -0400
-@@ -82,7 +82,7 @@ static inline void io_delay(void)
- static inline u16 ds(void)
- {
- 	u16 seg;
--	asm("movw %%ds,%0" : "=rm" (seg));
-+	asm volatile("movw %%ds,%0" : "=rm" (seg));
- 	return seg;
- }
- 
-@@ -178,7 +178,7 @@ static inline void wrgs32(u32 v, addr_t 
- static inline int memcmp(const void *s1, const void *s2, size_t len)
- {
- 	u8 diff;
--	asm("repe; cmpsb; setnz %0"
-+	asm volatile("repe; cmpsb; setnz %0"
- 	    : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
- 	return diff;
- }
-diff -urNp linux-2.6.34.1/arch/x86/boot/compressed/head_32.S \
                linux-2.6.34.1/arch/x86/boot/compressed/head_32.S
---- linux-2.6.34.1/arch/x86/boot/compressed/head_32.S	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/boot/compressed/head_32.S	2010-07-07 09:04:44.000000000 \
                -0400
-@@ -76,7 +76,7 @@ ENTRY(startup_32)
- 	notl	%eax
- 	andl    %eax, %ebx
- #else
--	movl	$LOAD_PHYSICAL_ADDR, %ebx
-+	movl	$____LOAD_PHYSICAL_ADDR, %ebx
- #endif
- 
- 	/* Target address to relocate to for decompression */
-@@ -149,7 +149,7 @@ relocated:
-  * and where it was actually loaded.
-  */
- 	movl	%ebp, %ebx
--	subl	$LOAD_PHYSICAL_ADDR, %ebx
-+	subl	$____LOAD_PHYSICAL_ADDR, %ebx
- 	jz	2f	/* Nothing to be done if loaded at compiled addr. */
- /*
-  * Process relocations.
-@@ -157,8 +157,7 @@ relocated:
- 
- 1:	subl	$4, %edi
- 	movl	(%edi), %ecx
--	testl	%ecx, %ecx
--	jz	2f
-+	jecxz	2f
- 	addl	%ebx, -__PAGE_OFFSET(%ebx, %ecx)
- 	jmp	1b
- 2:
-diff -urNp linux-2.6.34.1/arch/x86/boot/compressed/head_64.S \
                linux-2.6.34.1/arch/x86/boot/compressed/head_64.S
---- linux-2.6.34.1/arch/x86/boot/compressed/head_64.S	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/boot/compressed/head_64.S	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -91,7 +91,7 @@ ENTRY(startup_32)
- 	notl	%eax
- 	andl	%eax, %ebx
- #else
--	movl	$LOAD_PHYSICAL_ADDR, %ebx
-+	movl	$____LOAD_PHYSICAL_ADDR, %ebx
- #endif
- 
- 	/* Target address to relocate to for decompression */
-@@ -233,7 +233,7 @@ ENTRY(startup_64)
- 	notq	%rax
- 	andq	%rax, %rbp
- #else
--	movq	$LOAD_PHYSICAL_ADDR, %rbp
-+	movq	$____LOAD_PHYSICAL_ADDR, %rbp
- #endif
- 
- 	/* Target address to relocate to for decompression */
-diff -urNp linux-2.6.34.1/arch/x86/boot/compressed/misc.c \
                linux-2.6.34.1/arch/x86/boot/compressed/misc.c
---- linux-2.6.34.1/arch/x86/boot/compressed/misc.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/boot/compressed/misc.c	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -285,7 +285,7 @@ static void parse_elf(void *output)
- 		case PT_LOAD:
- #ifdef CONFIG_RELOCATABLE
- 			dest = output;
--			dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR);
-+			dest += (phdr->p_paddr - ____LOAD_PHYSICAL_ADDR);
- #else
- 			dest = (void *)(phdr->p_paddr);
- #endif
-@@ -332,7 +332,7 @@ asmlinkage void decompress_kernel(void *
- 		error("Destination address too large");
- #endif
- #ifndef CONFIG_RELOCATABLE
--	if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
-+	if ((unsigned long)output != ____LOAD_PHYSICAL_ADDR)
- 		error("Wrong destination address");
- #endif
- 
-diff -urNp linux-2.6.34.1/arch/x86/boot/compressed/mkpiggy.c \
                linux-2.6.34.1/arch/x86/boot/compressed/mkpiggy.c
---- linux-2.6.34.1/arch/x86/boot/compressed/mkpiggy.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/boot/compressed/mkpiggy.c	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -74,7 +74,7 @@ int main(int argc, char *argv[])
- 
- 	offs = (olen > ilen) ? olen - ilen : 0;
- 	offs += olen >> 12;	/* Add 8 bytes for each 32K block */
--	offs += 32*1024 + 18;	/* Add 32K + 18 bytes slack */
-+	offs += 64*1024;	/* Add 64K bytes slack */
- 	offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
- 
- 	printf(".section \".rodata.compressed\",\"a\", at progbits\n");
-diff -urNp linux-2.6.34.1/arch/x86/boot/compressed/relocs.c \
                linux-2.6.34.1/arch/x86/boot/compressed/relocs.c
---- linux-2.6.34.1/arch/x86/boot/compressed/relocs.c	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/boot/compressed/relocs.c	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -13,8 +13,11 @@
- 
- static void die(char *fmt, ...);
- 
-+#include "../../../../include/generated/autoconf.h"
-+
- #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
- static Elf32_Ehdr ehdr;
-+static Elf32_Phdr *phdr;
- static unsigned long reloc_count, reloc_idx;
- static unsigned long *relocs;
- 
-@@ -270,9 +273,39 @@ static void read_ehdr(FILE *fp)
- 	}
- }
- 
-+static void read_phdrs(FILE *fp)
-+{
-+	unsigned int i;
-+
-+	phdr = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr));
-+	if (!phdr) {
-+		die("Unable to allocate %d program headers\n",
-+		    ehdr.e_phnum);
-+	}
-+	if (fseek(fp, ehdr.e_phoff, SEEK_SET) < 0) {
-+		die("Seek to %d failed: %s\n",
-+			ehdr.e_phoff, strerror(errno));
-+	}
-+	if (fread(phdr, sizeof(*phdr), ehdr.e_phnum, fp) != ehdr.e_phnum) {
-+		die("Cannot read ELF program headers: %s\n",
-+			strerror(errno));
-+	}
-+	for(i = 0; i < ehdr.e_phnum; i++) {
-+		phdr[i].p_type      = elf32_to_cpu(phdr[i].p_type);
-+		phdr[i].p_offset    = elf32_to_cpu(phdr[i].p_offset);
-+		phdr[i].p_vaddr     = elf32_to_cpu(phdr[i].p_vaddr);
-+		phdr[i].p_paddr     = elf32_to_cpu(phdr[i].p_paddr);
-+		phdr[i].p_filesz    = elf32_to_cpu(phdr[i].p_filesz);
-+		phdr[i].p_memsz     = elf32_to_cpu(phdr[i].p_memsz);
-+		phdr[i].p_flags     = elf32_to_cpu(phdr[i].p_flags);
-+		phdr[i].p_align     = elf32_to_cpu(phdr[i].p_align);
-+	}
-+
-+}
-+
- static void read_shdrs(FILE *fp)
- {
--	int i;
-+	unsigned int i;
- 	Elf32_Shdr shdr;
- 
- 	secs = calloc(ehdr.e_shnum, sizeof(struct section));
-@@ -307,7 +340,7 @@ static void read_shdrs(FILE *fp)
- 
- static void read_strtabs(FILE *fp)
- {
--	int i;
-+	unsigned int i;
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		struct section *sec = &secs[i];
- 		if (sec->shdr.sh_type != SHT_STRTAB) {
-@@ -332,7 +365,7 @@ static void read_strtabs(FILE *fp)
- 
- static void read_symtabs(FILE *fp)
- {
--	int i,j;
-+	unsigned int i,j;
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		struct section *sec = &secs[i];
- 		if (sec->shdr.sh_type != SHT_SYMTAB) {
-@@ -365,7 +398,9 @@ static void read_symtabs(FILE *fp)
- 
- static void read_relocs(FILE *fp)
- {
--	int i,j;
-+	unsigned int i,j;
-+	uint32_t base;
-+
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		struct section *sec = &secs[i];
- 		if (sec->shdr.sh_type != SHT_REL) {
-@@ -385,9 +420,18 @@ static void read_relocs(FILE *fp)
- 			die("Cannot read symbol table: %s\n",
- 				strerror(errno));
- 		}
-+		base = 0;
-+		for (j = 0; j < ehdr.e_phnum; j++) {
-+			if (phdr[j].p_type != PT_LOAD )
-+				continue;
-+			if (secs[sec->shdr.sh_info].shdr.sh_offset < phdr[j].p_offset || \
                secs[sec->shdr.sh_info].shdr.sh_offset >= phdr[j].p_offset + \
                phdr[j].p_filesz)
-+				continue;
-+			base = CONFIG_PAGE_OFFSET + phdr[j].p_paddr - phdr[j].p_vaddr;
-+			break;
-+		}
- 		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
- 			Elf32_Rel *rel = &sec->reltab[j];
--			rel->r_offset = elf32_to_cpu(rel->r_offset);
-+			rel->r_offset = elf32_to_cpu(rel->r_offset) + base;
- 			rel->r_info   = elf32_to_cpu(rel->r_info);
- 		}
- 	}
-@@ -396,14 +440,14 @@ static void read_relocs(FILE *fp)
- 
- static void print_absolute_symbols(void)
- {
--	int i;
-+	unsigned int i;
- 	printf("Absolute symbols\n");
- 	printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		struct section *sec = &secs[i];
- 		char *sym_strtab;
- 		Elf32_Sym *sh_symtab;
--		int j;
-+		unsigned int j;
- 
- 		if (sec->shdr.sh_type != SHT_SYMTAB) {
- 			continue;
-@@ -431,14 +475,14 @@ static void print_absolute_symbols(void)
- 
- static void print_absolute_relocs(void)
- {
--	int i, printed = 0;
-+	unsigned int i, printed = 0;
- 
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		struct section *sec = &secs[i];
- 		struct section *sec_applies, *sec_symtab;
- 		char *sym_strtab;
- 		Elf32_Sym *sh_symtab;
--		int j;
-+		unsigned int j;
- 		if (sec->shdr.sh_type != SHT_REL) {
- 			continue;
- 		}
-@@ -499,13 +543,13 @@ static void print_absolute_relocs(void)
- 
- static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
- {
--	int i;
-+	unsigned int i;
- 	/* Walk through the relocations */
- 	for (i = 0; i < ehdr.e_shnum; i++) {
- 		char *sym_strtab;
- 		Elf32_Sym *sh_symtab;
- 		struct section *sec_applies, *sec_symtab;
--		int j;
-+		unsigned int j;
- 		struct section *sec = &secs[i];
- 
- 		if (sec->shdr.sh_type != SHT_REL) {
-@@ -530,6 +574,22 @@ static void walk_relocs(void (*visit)(El
- 			    !is_rel_reloc(sym_name(sym_strtab, sym))) {
- 				continue;
- 			}
-+			/* Don't relocate actual per-cpu variables, they are absolute indices, not \
                addresses */
-+			if (!strcmp(sec_name(sym->st_shndx), ".data.percpu") && \
                strcmp(sym_name(sym_strtab, sym), "__per_cpu_load"))
-+				continue;
-+
-+#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_X86_32)
-+			/* Don't relocate actual code, they are relocated implicitly by the base address \
                of KERNEL_CS */
-+			if (!strcmp(sec_name(sym->st_shndx), ".data") && !strcmp(sym_name(sym_strtab, \
                sym), "_etext"))
-+				continue;
-+			if (!strcmp(sec_name(sym->st_shndx), ".init.text"))
-+				continue;
-+			if (!strcmp(sec_name(sym->st_shndx), ".exit.text"))
-+				continue;
-+			if (!strcmp(sec_name(sym->st_shndx), ".text") && strcmp(sym_name(sym_strtab, \
                sym), "__LOAD_PHYSICAL_ADDR"))
-+				continue;
-+#endif
-+
- 			switch (r_type) {
- 			case R_386_NONE:
- 			case R_386_PC32:
-@@ -571,7 +631,7 @@ static int cmp_relocs(const void *va, co
- 
- static void emit_relocs(int as_text)
- {
--	int i;
-+	unsigned int i;
- 	/* Count how many relocations I have and allocate space for them. */
- 	reloc_count = 0;
- 	walk_relocs(count_reloc);
-@@ -665,6 +725,7 @@ int main(int argc, char **argv)
- 			fname, strerror(errno));
- 	}
- 	read_ehdr(fp);
-+	read_phdrs(fp);
- 	read_shdrs(fp);
- 	read_strtabs(fp);
- 	read_symtabs(fp);
-diff -urNp linux-2.6.34.1/arch/x86/boot/cpucheck.c \
                linux-2.6.34.1/arch/x86/boot/cpucheck.c
---- linux-2.6.34.1/arch/x86/boot/cpucheck.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/cpucheck.c	2010-07-07 09:04:45.000000000 -0400
-@@ -74,7 +74,7 @@ static int has_fpu(void)
- 	u16 fcw = -1, fsw = -1;
- 	u32 cr0;
- 
--	asm("movl %%cr0,%0" : "=r" (cr0));
-+	asm volatile("movl %%cr0,%0" : "=r" (cr0));
- 	if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
- 		cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
- 		asm volatile("movl %0,%%cr0" : : "r" (cr0));
-@@ -90,7 +90,7 @@ static int has_eflag(u32 mask)
- {
- 	u32 f0, f1;
- 
--	asm("pushfl ; "
-+	asm volatile("pushfl ; "
- 	    "pushfl ; "
- 	    "popl %0 ; "
- 	    "movl %0,%1 ; "
-@@ -115,7 +115,7 @@ static void get_flags(void)
- 		set_bit(X86_FEATURE_FPU, cpu.flags);
- 
- 	if (has_eflag(X86_EFLAGS_ID)) {
--		asm("cpuid"
-+		asm volatile("cpuid"
- 		    : "=a" (max_intel_level),
- 		      "=b" (cpu_vendor[0]),
- 		      "=d" (cpu_vendor[1]),
-@@ -124,7 +124,7 @@ static void get_flags(void)
- 
- 		if (max_intel_level >= 0x00000001 &&
- 		    max_intel_level <= 0x0000ffff) {
--			asm("cpuid"
-+			asm volatile("cpuid"
- 			    : "=a" (tfms),
- 			      "=c" (cpu.flags[4]),
- 			      "=d" (cpu.flags[0])
-@@ -136,7 +136,7 @@ static void get_flags(void)
- 				cpu.model += ((tfms >> 16) & 0xf) << 4;
- 		}
- 
--		asm("cpuid"
-+		asm volatile("cpuid"
- 		    : "=a" (max_amd_level)
- 		    : "a" (0x80000000)
- 		    : "ebx", "ecx", "edx");
-@@ -144,7 +144,7 @@ static void get_flags(void)
- 		if (max_amd_level >= 0x80000001 &&
- 		    max_amd_level <= 0x8000ffff) {
- 			u32 eax = 0x80000001;
--			asm("cpuid"
-+			asm volatile("cpuid"
- 			    : "+a" (eax),
- 			      "=c" (cpu.flags[6]),
- 			      "=d" (cpu.flags[1])
-@@ -203,9 +203,9 @@ int check_cpu(int *cpu_level_ptr, int *r
- 		u32 ecx = MSR_K7_HWCR;
- 		u32 eax, edx;
- 
--		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
-+		asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
- 		eax &= ~(1 << 15);
--		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
-+		asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
- 
- 		get_flags();	/* Make sure it really did something */
- 		err = check_flags();
-@@ -218,9 +218,9 @@ int check_cpu(int *cpu_level_ptr, int *r
- 		u32 ecx = MSR_VIA_FCR;
- 		u32 eax, edx;
- 
--		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
-+		asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
- 		eax |= (1<<1)|(1<<7);
--		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
-+		asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
- 
- 		set_bit(X86_FEATURE_CX8, cpu.flags);
- 		err = check_flags();
-@@ -231,12 +231,12 @@ int check_cpu(int *cpu_level_ptr, int *r
- 		u32 eax, edx;
- 		u32 level = 1;
- 
--		asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
--		asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
--		asm("cpuid"
-+		asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
-+		asm volatile("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
-+		asm volatile("cpuid"
- 		    : "+a" (level), "=d" (cpu.flags[0])
- 		    : : "ecx", "ebx");
--		asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
-+		asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
- 
- 		err = check_flags();
- 	}
-diff -urNp linux-2.6.34.1/arch/x86/boot/header.S \
                linux-2.6.34.1/arch/x86/boot/header.S
---- linux-2.6.34.1/arch/x86/boot/header.S	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/header.S	2010-07-07 09:04:45.000000000 -0400
-@@ -224,7 +224,7 @@ setup_data:		.quad 0			# 64-bit physical
- 						# single linked list of
- 						# struct setup_data
- 
--pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
-+pref_address:		.quad ____LOAD_PHYSICAL_ADDR	# preferred load addr
- 
- #define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_extract_offset)
- #define VO_INIT_SIZE	(VO__end - VO__text)
-diff -urNp linux-2.6.34.1/arch/x86/boot/memory.c \
                linux-2.6.34.1/arch/x86/boot/memory.c
---- linux-2.6.34.1/arch/x86/boot/memory.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/memory.c	2010-07-07 09:04:45.000000000 -0400
-@@ -19,7 +19,7 @@
- 
- static int detect_memory_e820(void)
- {
--	int count = 0;
-+	unsigned int count = 0;
- 	struct biosregs ireg, oreg;
- 	struct e820entry *desc = boot_params.e820_map;
- 	static struct e820entry buf; /* static so it is zeroed */
-diff -urNp linux-2.6.34.1/arch/x86/boot/video-vesa.c \
                linux-2.6.34.1/arch/x86/boot/video-vesa.c
---- linux-2.6.34.1/arch/x86/boot/video-vesa.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/video-vesa.c	2010-07-07 09:04:45.000000000 -0400
-@@ -200,6 +200,7 @@ static void vesa_store_pm_info(void)
- 
- 	boot_params.screen_info.vesapm_seg = oreg.es;
- 	boot_params.screen_info.vesapm_off = oreg.di;
-+	boot_params.screen_info.vesapm_size = oreg.cx;
- }
- 
- /*
-diff -urNp linux-2.6.34.1/arch/x86/boot/video.c linux-2.6.34.1/arch/x86/boot/video.c
---- linux-2.6.34.1/arch/x86/boot/video.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/boot/video.c	2010-07-07 09:04:45.000000000 -0400
-@@ -96,7 +96,7 @@ static void store_mode_params(void)
- static unsigned int get_entry(void)
- {
- 	char entry_buf[4];
--	int i, len = 0;
-+	unsigned int i, len = 0;
- 	int key;
- 	unsigned int v;
- 
-diff -urNp linux-2.6.34.1/arch/x86/ia32/ia32_signal.c \
                linux-2.6.34.1/arch/x86/ia32/ia32_signal.c
---- linux-2.6.34.1/arch/x86/ia32/ia32_signal.c	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/ia32/ia32_signal.c	2010-07-07 09:04:45.000000000 -0400
-@@ -403,7 +403,7 @@ static void __user *get_sigframe(struct 
- 	sp -= frame_size;
- 	/* Align the stack pointer according to the i386 ABI,
- 	 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
--	sp = ((sp + 4) & -16ul) - 4;
-+	sp = ((sp - 12) & -16ul) - 4;
- 	return (void __user *) sp;
- }
- 
-@@ -503,7 +503,7 @@ int ia32_setup_rt_frame(int sig, struct 
- 		0xb8,
- 		__NR_ia32_rt_sigreturn,
- 		0x80cd,
--		0,
-+		0
- 	};
- 
- 	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
-diff -urNp linux-2.6.34.1/arch/x86/ia32/ia32entry.S \
                linux-2.6.34.1/arch/x86/ia32/ia32entry.S
---- linux-2.6.34.1/arch/x86/ia32/ia32entry.S	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/ia32/ia32entry.S	2010-07-07 09:04:45.000000000 -0400
-@@ -13,6 +13,7 @@
- #include <asm/thread_info.h>	
- #include <asm/segment.h>
- #include <asm/irqflags.h>
-+#include <asm/pgtable.h>
- #include <linux/linkage.h>
- 
- /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
-@@ -114,6 +115,11 @@ ENTRY(ia32_sysenter_target)
- 	SWAPGS_UNSAFE_STACK
- 	movq	PER_CPU_VAR(kernel_stack), %rsp
- 	addq	$(KERNEL_STACK_OFFSET),%rsp
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	call pax_enter_kernel_user
-+#endif
-+
- 	/*
- 	 * No need to follow this irqs on/off section: the syscall
- 	 * disabled irqs, here we enable it straight after entry:
-@@ -144,6 +150,12 @@ ENTRY(ia32_sysenter_target)
- 	SAVE_ARGS 0,0,1
-  	/* no need to do an access_ok check here because rbp has been
-  	   32bit zero extended */ 
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	mov $PAX_USER_SHADOW_BASE,%r10
-+	add %r10,%rbp
-+#endif
-+
- 1:	movl	(%rbp),%ebp
-  	.section __ex_table,"a"
-  	.quad 1b,ia32_badarg
-@@ -166,6 +178,11 @@ sysenter_dispatch:
- 	testl	$_TIF_ALLWORK_MASK,TI_flags(%r10)
- 	jnz	sysexit_audit
- sysexit_from_sys_call:
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	call pax_exit_kernel_user
-+#endif
-+
- 	andl    $~TS_COMPAT,TI_status(%r10)
- 	/* clear IF, that popfq doesn't enable interrupts early */
- 	andl  $~0x200,EFLAGS-R11(%rsp) 
-@@ -284,6 +301,11 @@ ENTRY(ia32_cstar_target)
- 	movl	%esp,%r8d
- 	CFI_REGISTER	rsp,r8
- 	movq	PER_CPU_VAR(kernel_stack),%rsp
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	call pax_enter_kernel_user
-+#endif
-+
- 	/*
- 	 * No need to follow this irqs on/off section: the syscall
- 	 * disabled irqs and here we enable it straight after entry:
-@@ -305,6 +327,12 @@ ENTRY(ia32_cstar_target)
- 	/* no need to do an access_ok check here because r8 has been
- 	   32bit zero extended */ 
- 	/* hardware stack frame is complete now */	
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	mov $PAX_USER_SHADOW_BASE,%r10
-+	add %r10,%r8
-+#endif
-+
- 1:	movl	(%r8),%r9d
- 	.section __ex_table,"a"
- 	.quad 1b,ia32_badarg
-@@ -327,6 +355,11 @@ cstar_dispatch:
- 	testl $_TIF_ALLWORK_MASK,TI_flags(%r10)
- 	jnz sysretl_audit
- sysretl_from_sys_call:
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	call pax_exit_kernel_user
-+#endif
-+
- 	andl $~TS_COMPAT,TI_status(%r10)
- 	RESTORE_ARGS 1,-ARG_SKIP,1,1,1
- 	movl RIP-ARGOFFSET(%rsp),%ecx
-@@ -409,6 +442,11 @@ ENTRY(ia32_syscall)
- 	CFI_REL_OFFSET	rip,RIP-RIP
- 	PARAVIRT_ADJUST_EXCEPTION_FRAME
- 	SWAPGS
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+	call pax_enter_kernel_user
-+#endif
-+
- 	/*
- 	 * No need to follow this irqs on/off section: the syscall
- 	 * disabled irqs and here we enable it straight after entry:
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/alternative.h \
                linux-2.6.34.1/arch/x86/include/asm/alternative.h
---- linux-2.6.34.1/arch/x86/include/asm/alternative.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/alternative.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -91,7 +91,7 @@ static inline int alternatives_text_rese
-       "	 .byte 664f-663f\n"			/* replacementlen  */	\
-       "	 .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */	\
-       ".previous\n"							\
--      ".section .altinstr_replacement, \"ax\"\n"			\
-+      ".section .altinstr_replacement, \"a\"\n"			\
-       "663:\n\t" newinstr "\n664:\n"		/* replacement     */	\
-       ".previous"
- 
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/apm.h \
                linux-2.6.34.1/arch/x86/include/asm/apm.h
---- linux-2.6.34.1/arch/x86/include/asm/apm.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/apm.h	2010-07-07 09:04:45.000000000 -0400
-@@ -34,7 +34,7 @@ static inline void apm_bios_call_asm(u32
- 	__asm__ __volatile__(APM_DO_ZERO_SEGS
- 		"pushl %%edi\n\t"
- 		"pushl %%ebp\n\t"
--		"lcall *%%cs:apm_bios_entry\n\t"
-+		"lcall *%%ss:apm_bios_entry\n\t"
- 		"setc %%al\n\t"
- 		"popl %%ebp\n\t"
- 		"popl %%edi\n\t"
-@@ -58,7 +58,7 @@ static inline u8 apm_bios_call_simple_as
- 	__asm__ __volatile__(APM_DO_ZERO_SEGS
- 		"pushl %%edi\n\t"
- 		"pushl %%ebp\n\t"
--		"lcall *%%cs:apm_bios_entry\n\t"
-+		"lcall *%%ss:apm_bios_entry\n\t"
- 		"setc %%bl\n\t"
- 		"popl %%ebp\n\t"
- 		"popl %%edi\n\t"
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/asm.h \
                linux-2.6.34.1/arch/x86/include/asm/asm.h
---- linux-2.6.34.1/arch/x86/include/asm/asm.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/asm.h	2010-07-07 09:04:45.000000000 -0400
-@@ -37,6 +37,12 @@
- #define _ASM_SI		__ASM_REG(si)
- #define _ASM_DI		__ASM_REG(di)
- 
-+#ifdef CONFIG_X86_32
-+#define _ASM_INTO	"into"
-+#else
-+#define _ASM_INTO	"int $4"
-+#endif
-+
- /* Exception table entry */
- #ifdef __ASSEMBLY__
- # define _ASM_EXTABLE(from,to)	    \
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/atomic.h \
                linux-2.6.34.1/arch/x86/include/asm/atomic.h
---- linux-2.6.34.1/arch/x86/include/asm/atomic.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/atomic.h	2010-07-07 09:04:45.000000000 -0400
-@@ -26,6 +26,17 @@ static inline int atomic_read(const atom
- }
- 
- /**
-+ * atomic_read_unchecked - read atomic variable
-+ * @v: pointer of type atomic_unchecked_t
-+ *
-+ * Atomically reads the value of @v.
-+ */
-+static inline int atomic_read_unchecked(const atomic_unchecked_t *v)
-+{
-+	return v->counter;
-+}
-+
-+/**
-  * atomic_set - set atomic variable
-  * @v: pointer of type atomic_t
-  * @i: required value
-@@ -38,6 +49,18 @@ static inline void atomic_set(atomic_t *
- }
- 
- /**
-+ * atomic_set_unchecked - set atomic variable
-+ * @v: pointer of type atomic_unchecked_t
-+ * @i: required value
-+ *
-+ * Atomically sets the value of @v to @i.
-+ */
-+static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i)
-+{
-+	v->counter = i;
-+}
-+
-+/**
-  * atomic_add - add integer to atomic variable
-  * @i: integer value to add
-  * @v: pointer of type atomic_t
-@@ -46,7 +69,29 @@ static inline void atomic_set(atomic_t *
-  */
- static inline void atomic_add(int i, atomic_t *v)
- {
--	asm volatile(LOCK_PREFIX "addl %1,%0"
-+	asm volatile(LOCK_PREFIX "addl %1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "subl %1,%0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+m" (v->counter)
-+		     : "ir" (i));
-+}
-+
-+/**
-+ * atomic_add_unchecked - add integer to atomic variable
-+ * @i: integer value to add
-+ * @v: pointer of type atomic_unchecked_t
-+ *
-+ * Atomically adds @i to @v.
-+ */
-+static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v)
-+{
-+	asm volatile(LOCK_PREFIX "addl %1,%0\n"
- 		     : "+m" (v->counter)
- 		     : "ir" (i));
- }
-@@ -60,7 +105,29 @@ static inline void atomic_add(int i, ato
-  */
- static inline void atomic_sub(int i, atomic_t *v)
- {
--	asm volatile(LOCK_PREFIX "subl %1,%0"
-+	asm volatile(LOCK_PREFIX "subl %1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "addl %1,%0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+m" (v->counter)
-+		     : "ir" (i));
-+}
-+
-+/**
-+ * atomic_sub_unchecked - subtract integer from atomic variable
-+ * @i: integer value to subtract
-+ * @v: pointer of type atomic_t
-+ *
-+ * Atomically subtracts @i from @v.
-+ */
-+static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v)
-+{
-+	asm volatile(LOCK_PREFIX "subl %1,%0\n"
- 		     : "+m" (v->counter)
- 		     : "ir" (i));
- }
-@@ -78,7 +145,16 @@ static inline int atomic_sub_and_test(in
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
-+	asm volatile(LOCK_PREFIX "subl %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "addl %2,%0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (v->counter), "=qm" (c)
- 		     : "ir" (i) : "memory");
- 	return c;
-@@ -92,7 +168,27 @@ static inline int atomic_sub_and_test(in
-  */
- static inline void atomic_inc(atomic_t *v)
- {
--	asm volatile(LOCK_PREFIX "incl %0"
-+	asm volatile(LOCK_PREFIX "incl %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "decl %0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+m" (v->counter));
-+}
-+
-+/**
-+ * atomic_inc_unchecked - increment atomic variable
-+ * @v: pointer of type atomic_unchecked_t
-+ *
-+ * Atomically increments @v by 1.
-+ */
-+static inline void atomic_inc_unchecked(atomic_unchecked_t *v)
-+{
-+	asm volatile(LOCK_PREFIX "incl %0\n"
- 		     : "+m" (v->counter));
- }
- 
-@@ -104,7 +200,27 @@ static inline void atomic_inc(atomic_t *
-  */
- static inline void atomic_dec(atomic_t *v)
- {
--	asm volatile(LOCK_PREFIX "decl %0"
-+	asm volatile(LOCK_PREFIX "decl %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "incl %0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+m" (v->counter));
-+}
-+
-+/**
-+ * atomic_dec_unchecked - decrement atomic variable
-+ * @v: pointer of type atomic_t
-+ *
-+ * Atomically decrements @v by 1.
-+ */
-+static inline void atomic_dec_unchecked(atomic_unchecked_t *v)
-+{
-+	asm volatile(LOCK_PREFIX "decl %0\n"
- 		     : "+m" (v->counter));
- }
- 
-@@ -120,7 +236,16 @@ static inline int atomic_dec_and_test(at
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "decl %0; sete %1"
-+	asm volatile(LOCK_PREFIX "decl %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "incl %0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (v->counter), "=qm" (c)
- 		     : : "memory");
- 	return c != 0;
-@@ -138,7 +263,16 @@ static inline int atomic_inc_and_test(at
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "incl %0; sete %1"
-+	asm volatile(LOCK_PREFIX "incl %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "decl %0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (v->counter), "=qm" (c)
- 		     : : "memory");
- 	return c != 0;
-@@ -157,7 +291,16 @@ static inline int atomic_add_negative(in
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
-+	asm volatile(LOCK_PREFIX "addl %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "subl %2,%0\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sets %1\n"
- 		     : "+m" (v->counter), "=qm" (c)
- 		     : "ir" (i) : "memory");
- 	return c;
-@@ -180,6 +323,46 @@ static inline int atomic_add_return(int 
- #endif
- 	/* Modern 486+ processor */
- 	__i = i;
-+	asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "movl %0, %1\n"
-+		     _ASM_INTO "\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+r" (i), "+m" (v->counter)
-+		     : : "memory");
-+	return i + __i;
-+
-+#ifdef CONFIG_M386
-+no_xadd: /* Legacy 386 processor */
-+	local_irq_save(flags);
-+	__i = atomic_read(v);
-+	atomic_set(v, i + __i);
-+	local_irq_restore(flags);
-+	return i + __i;
-+#endif
-+}
-+
-+/**
-+ * atomic_add_return_unchecked - add integer and return
-+ * @v: pointer of type atomic_unchecked_t
-+ * @i: integer value to add
-+ *
-+ * Atomically adds @i to @v and returns @i + @v
-+ */
-+static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v)
-+{
-+	int __i;
-+#ifdef CONFIG_M386
-+	unsigned long flags;
-+	if (unlikely(boot_cpu_data.x86 <= 3))
-+		goto no_xadd;
-+#endif
-+	/* Modern 486+ processor */
-+	__i = i;
- 	asm volatile(LOCK_PREFIX "xaddl %0, %1"
- 		     : "+r" (i), "+m" (v->counter)
- 		     : : "memory");
-@@ -208,6 +391,7 @@ static inline int atomic_sub_return(int 
- }
- 
- #define atomic_inc_return(v)  (atomic_add_return(1, v))
-+#define atomic_inc_return_unchecked(v)  (atomic_add_return_unchecked(1, v))
- #define atomic_dec_return(v)  (atomic_sub_return(1, v))
- 
- static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-@@ -231,17 +415,29 @@ static inline int atomic_xchg(atomic_t *
-  */
- static inline int atomic_add_unless(atomic_t *v, int a, int u)
- {
--	int c, old;
-+	int c, old, new;
- 	c = atomic_read(v);
- 	for (;;) {
--		if (unlikely(c == (u)))
-+		if (unlikely(c == u))
- 			break;
--		old = atomic_cmpxchg((v), c, c + (a));
-+
-+		asm volatile("addl %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+			     "jno 0f\n"
-+			     _ASM_INTO "\n0:\n"
-+			     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+			     : "=r" (new)
-+			     : "0" (c), "ir" (a));
-+
-+		old = atomic_cmpxchg(v, c, new);
- 		if (likely(old == c))
- 			break;
- 		c = old;
- 	}
--	return c != (u);
-+	return c != u;
- }
- 
- #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/atomic64_32.h \
                linux-2.6.34.1/arch/x86/include/asm/atomic64_32.h
---- linux-2.6.34.1/arch/x86/include/asm/atomic64_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/atomic64_32.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -12,6 +12,14 @@ typedef struct {
- 	u64 __aligned(8) counter;
- } atomic64_t;
- 
-+#ifdef CONFIG_PAX_REFCOUNT
-+typedef struct {
-+	u64 __aligned(8) counter;
-+} atomic64_unchecked_t;
-+#else
-+typedef atomic64_t atomic64_unchecked_t;
-+#endif
-+
- #define ATOMIC64_INIT(val)	{ (val) }
- 
- extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/atomic64_64.h \
                linux-2.6.34.1/arch/x86/include/asm/atomic64_64.h
---- linux-2.6.34.1/arch/x86/include/asm/atomic64_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/atomic64_64.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -22,6 +22,18 @@ static inline long atomic64_read(const a
- }
- 
- /**
-+ * atomic64_read_unchecked - read atomic64 variable
-+ * @v: pointer of type atomic64_unchecked_t
-+ *
-+ * Atomically reads the value of @v.
-+ * Doesn't imply a read memory barrier.
-+ */
-+static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v)
-+{
-+	return v->counter;
-+}
-+
-+/**
-  * atomic64_set - set atomic64 variable
-  * @v: pointer to type atomic64_t
-  * @i: required value
-@@ -34,6 +46,18 @@ static inline void atomic64_set(atomic64
- }
- 
- /**
-+ * atomic64_set_unchecked - set atomic64 variable
-+ * @v: pointer to type atomic64_unchecked_t
-+ * @i: required value
-+ *
-+ * Atomically sets the value of @v to @i.
-+ */
-+static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i)
-+{
-+	v->counter = i;
-+}
-+
-+/**
-  * atomic64_add - add integer to atomic64 variable
-  * @i: integer value to add
-  * @v: pointer to type atomic64_t
-@@ -42,6 +66,28 @@ static inline void atomic64_set(atomic64
-  */
- static inline void atomic64_add(long i, atomic64_t *v)
- {
-+	asm volatile(LOCK_PREFIX "addq %1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "subq %1,%0\n"
-+		     "int $4\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "=m" (v->counter)
-+		     : "er" (i), "m" (v->counter));
-+}
-+
-+/**
-+ * atomic64_add_unchecked - add integer to atomic64 variable
-+ * @i: integer value to add
-+ * @v: pointer to type atomic64_unchecked_t
-+ *
-+ * Atomically adds @i to @v.
-+ */
-+static inline void atomic64_add_unchecked(long i, atomic64_unchecked_t *v)
-+{
- 	asm volatile(LOCK_PREFIX "addq %1,%0"
- 		     : "=m" (v->counter)
- 		     : "er" (i), "m" (v->counter));
-@@ -56,7 +102,15 @@ static inline void atomic64_add(long i, 
-  */
- static inline void atomic64_sub(long i, atomic64_t *v)
- {
--	asm volatile(LOCK_PREFIX "subq %1,%0"
-+	asm volatile(LOCK_PREFIX "subq %1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "addq %1,%0\n"
-+		     "int $4\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
- 		     : "=m" (v->counter)
- 		     : "er" (i), "m" (v->counter));
- }
-@@ -74,7 +128,16 @@ static inline int atomic64_sub_and_test(
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
-+	asm volatile(LOCK_PREFIX "subq %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "addq %2,%0\n"
-+		     "int $4\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "=m" (v->counter), "=qm" (c)
- 		     : "er" (i), "m" (v->counter) : "memory");
- 	return c;
-@@ -88,6 +151,31 @@ static inline int atomic64_sub_and_test(
-  */
- static inline void atomic64_inc(atomic64_t *v)
- {
-+	asm volatile(LOCK_PREFIX "incq %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     LOCK_PREFIX "decq %0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     : "=m" (v->counter)
-+		     : "m" (v->counter));
-+}
-+
-+/**
-+ * atomic64_inc_unchecked - increment atomic64 variable
-+ * @v: pointer to type atomic64_unchecked_t
-+ *
-+ * Atomically increments @v by 1.
-+ */
-+static inline void atomic64_inc_unchecked(atomic64_unchecked_t *v)
-+{
- 	asm volatile(LOCK_PREFIX "incq %0"
- 		     : "=m" (v->counter)
- 		     : "m" (v->counter));
-@@ -101,7 +189,32 @@ static inline void atomic64_inc(atomic64
-  */
- static inline void atomic64_dec(atomic64_t *v)
- {
--	asm volatile(LOCK_PREFIX "decq %0"
-+	asm volatile(LOCK_PREFIX "decq %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1: \n"
-+		     LOCK_PREFIX "incq %0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     : "=m" (v->counter)
-+		     : "m" (v->counter));
-+}
-+
-+/**
-+ * atomic64_dec_unchecked - decrement atomic64 variable
-+ * @v: pointer to type atomic64_t
-+ *
-+ * Atomically decrements @v by 1.
-+ */
-+static inline void atomic64_dec_unchecked(atomic64_unchecked_t *v)
-+{
-+	asm volatile(LOCK_PREFIX "decq %0\n"
- 		     : "=m" (v->counter)
- 		     : "m" (v->counter));
- }
-@@ -118,7 +231,20 @@ static inline int atomic64_dec_and_test(
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "decq %0; sete %1"
-+	asm volatile(LOCK_PREFIX "decq %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1: \n"
-+		     LOCK_PREFIX "incq %0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "=m" (v->counter), "=qm" (c)
- 		     : "m" (v->counter) : "memory");
- 	return c != 0;
-@@ -136,7 +262,20 @@ static inline int atomic64_inc_and_test(
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "incq %0; sete %1"
-+	asm volatile(LOCK_PREFIX "incq %0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1: \n"
-+		     LOCK_PREFIX "decq %0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "=m" (v->counter), "=qm" (c)
- 		     : "m" (v->counter) : "memory");
- 	return c != 0;
-@@ -155,7 +294,16 @@ static inline int atomic64_add_negative(
- {
- 	unsigned char c;
- 
--	asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
-+	asm volatile(LOCK_PREFIX "addq %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     LOCK_PREFIX "subq %2,%0\n"
-+		     "int $4\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     "sets %1\n"
- 		     : "=m" (v->counter), "=qm" (c)
- 		     : "er" (i), "m" (v->counter) : "memory");
- 	return c;
-@@ -171,7 +319,31 @@ static inline int atomic64_add_negative(
- static inline long atomic64_add_return(long i, atomic64_t *v)
- {
- 	long __i = i;
--	asm volatile(LOCK_PREFIX "xaddq %0, %1;"
-+	asm volatile(LOCK_PREFIX "xaddq %0, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+		     "jno 0f\n"
-+		     "movq %0, %1\n"
-+		     "int $4\n0:\n"
-+		     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+		     : "+r" (i), "+m" (v->counter)
-+		     : : "memory");
-+	return i + __i;
-+}
-+
-+/**
-+ * atomic64_add_return_unchecked - add and return
-+ * @i: integer value to add
-+ * @v: pointer to type atomic64_unchecked_t
-+ *
-+ * Atomically adds @i to @v and returns @i + @v
-+ */
-+static inline long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v)
-+{
-+	long __i = i;
-+	asm volatile(LOCK_PREFIX "xaddq %0, %1"
- 		     : "+r" (i), "+m" (v->counter)
- 		     : : "memory");
- 	return i + __i;
-@@ -183,6 +355,7 @@ static inline long atomic64_sub_return(l
- }
- 
- #define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
-+#define atomic64_inc_return_unchecked(v)  (atomic64_add_return_unchecked(1, (v)))
- #define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
- 
- static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
-@@ -206,17 +379,29 @@ static inline long atomic64_xchg(atomic6
-  */
- static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
- {
--	long c, old;
-+	long c, old, new;
- 	c = atomic64_read(v);
- 	for (;;) {
--		if (unlikely(c == (u)))
-+		if (unlikely(c == u))
- 			break;
--		old = atomic64_cmpxchg((v), c, c + (a));
-+
-+		asm volatile("add %2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+			     "jno 0f\n"
-+			     "int $4\n0:\n"
-+			     _ASM_EXTABLE(0b, 0b)
-+#endif
-+
-+			     : "=r" (new)
-+			     : "0" (c), "ir" (a));
-+
-+		old = atomic64_cmpxchg(v, c, new);
- 		if (likely(old == c))
- 			break;
- 		c = old;
- 	}
--	return c != (u);
-+	return c != u;
- }
- 
- #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/boot.h \
                linux-2.6.34.1/arch/x86/include/asm/boot.h
---- linux-2.6.34.1/arch/x86/include/asm/boot.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/boot.h	2010-07-07 09:04:45.000000000 -0400
-@@ -11,10 +11,15 @@
- #include <asm/pgtable_types.h>
- 
- /* Physical address where kernel should be loaded. */
--#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
-+#define ____LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
- 				+ (CONFIG_PHYSICAL_ALIGN - 1)) \
- 				& ~(CONFIG_PHYSICAL_ALIGN - 1))
- 
-+#ifndef __ASSEMBLY__
-+extern unsigned char __LOAD_PHYSICAL_ADDR[];
-+#define LOAD_PHYSICAL_ADDR ((unsigned long)__LOAD_PHYSICAL_ADDR)
-+#endif
-+
- /* Minimum kernel alignment, as a power of two */
- #ifdef CONFIG_X86_64
- #define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/cache.h \
                linux-2.6.34.1/arch/x86/include/asm/cache.h
---- linux-2.6.34.1/arch/x86/include/asm/cache.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/cache.h	2010-07-07 09:04:45.000000000 -0400
-@@ -8,6 +8,7 @@
- #define L1_CACHE_BYTES	(1 << L1_CACHE_SHIFT)
- 
- #define __read_mostly __attribute__((__section__(".data.read_mostly")))
-+#define __read_only __attribute__((__section__(".data.read_only")))
- 
- #define INTERNODE_CACHE_SHIFT CONFIG_X86_INTERNODE_CACHE_SHIFT
- #define INTERNODE_CACHE_BYTES (1 << INTERNODE_CACHE_SHIFT)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/cacheflush.h \
                linux-2.6.34.1/arch/x86/include/asm/cacheflush.h
---- linux-2.6.34.1/arch/x86/include/asm/cacheflush.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/cacheflush.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -61,7 +61,7 @@ PAGEFLAG(WC, WC)
- static inline unsigned long get_page_memtype(struct page *pg)
- {
- 	if (!PageUncached(pg) && !PageWC(pg))
--		return -1;
-+		return ~0UL;
- 	else if (!PageUncached(pg) && PageWC(pg))
- 		return _PAGE_CACHE_WC;
- 	else if (PageUncached(pg) && !PageWC(pg))
-@@ -86,7 +86,7 @@ static inline void set_page_memtype(stru
- 		SetPageWC(pg);
- 		break;
- 	default:
--	case -1:
-+	case ~0UL:
- 		ClearPageUncached(pg);
- 		ClearPageWC(pg);
- 		break;
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/checksum_32.h \
                linux-2.6.34.1/arch/x86/include/asm/checksum_32.h
---- linux-2.6.34.1/arch/x86/include/asm/checksum_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/checksum_32.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -31,6 +31,14 @@ asmlinkage __wsum csum_partial_copy_gene
- 					    int len, __wsum sum,
- 					    int *src_err_ptr, int *dst_err_ptr);
- 
-+asmlinkage __wsum csum_partial_copy_generic_to_user(const void *src, void *dst,
-+						  int len, __wsum sum,
-+						  int *src_err_ptr, int *dst_err_ptr);
-+
-+asmlinkage __wsum csum_partial_copy_generic_from_user(const void *src, void *dst,
-+						  int len, __wsum sum,
-+						  int *src_err_ptr, int *dst_err_ptr);
-+
- /*
-  *	Note: when you get a NULL pointer exception here this means someone
-  *	passed in an incorrect kernel address to one of these functions.
-@@ -50,7 +58,7 @@ static inline __wsum csum_partial_copy_f
- 						 int *err_ptr)
- {
- 	might_sleep();
--	return csum_partial_copy_generic((__force void *)src, dst,
-+	return csum_partial_copy_generic_from_user((__force void *)src, dst,
- 					 len, sum, err_ptr, NULL);
- }
- 
-@@ -178,7 +186,7 @@ static inline __wsum csum_and_copy_to_us
- {
- 	might_sleep();
- 	if (access_ok(VERIFY_WRITE, dst, len))
--		return csum_partial_copy_generic(src, (__force void *)dst,
-+		return csum_partial_copy_generic_to_user(src, (__force void *)dst,
- 						 len, sum, NULL, err_ptr);
- 
- 	if (len)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/desc.h \
                linux-2.6.34.1/arch/x86/include/asm/desc.h
---- linux-2.6.34.1/arch/x86/include/asm/desc.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/desc.h	2010-07-07 09:04:45.000000000 -0400
-@@ -4,6 +4,7 @@
- #include <asm/desc_defs.h>
- #include <asm/ldt.h>
- #include <asm/mmu.h>
-+#include <asm/pgtable.h>
- #include <linux/smp.h>
- 
- static inline void fill_ldt(struct desc_struct *desc,
-@@ -15,6 +16,7 @@ static inline void fill_ldt(struct desc_
- 	desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
- 	desc->type = (info->read_exec_only ^ 1) << 1;
- 	desc->type |= info->contents << 2;
-+	desc->type |= info->seg_not_present ^ 1;
- 	desc->s = 1;
- 	desc->dpl = 0x3;
- 	desc->p = info->seg_not_present ^ 1;
-@@ -31,16 +33,12 @@ static inline void fill_ldt(struct desc_
- }
- 
- extern struct desc_ptr idt_descr;
--extern gate_desc idt_table[];
--
--struct gdt_page {
--	struct desc_struct gdt[GDT_ENTRIES];
--} __attribute__((aligned(PAGE_SIZE)));
--DECLARE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page);
-+extern gate_desc idt_table[256];
- 
-+extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct \
                desc_struct)];
- static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
- {
--	return per_cpu(gdt_page, cpu).gdt;
-+	return cpu_gdt_table[cpu];
- }
- 
- #ifdef CONFIG_X86_64
-@@ -115,19 +113,24 @@ static inline void paravirt_free_ldt(str
- static inline void native_write_idt_entry(gate_desc *idt, int entry,
- 					  const gate_desc *gate)
- {
-+	pax_open_kernel();
- 	memcpy(&idt[entry], gate, sizeof(*gate));
-+	pax_close_kernel();
- }
- 
- static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
- 					  const void *desc)
- {
-+	pax_open_kernel();
- 	memcpy(&ldt[entry], desc, 8);
-+	pax_close_kernel();
- }
- 
- static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
- 					  const void *desc, int type)
- {
- 	unsigned int size;
-+
- 	switch (type) {
- 	case DESC_TSS:
- 		size = sizeof(tss_desc);
-@@ -139,7 +142,10 @@ static inline void native_write_gdt_entr
- 		size = sizeof(struct desc_struct);
- 		break;
- 	}
-+
-+	pax_open_kernel();
- 	memcpy(&gdt[entry], desc, size);
-+	pax_close_kernel();
- }
- 
- static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
-@@ -211,7 +217,9 @@ static inline void native_set_ldt(const 
- 
- static inline void native_load_tr_desc(void)
- {
-+	pax_open_kernel();
- 	asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
-+	pax_close_kernel();
- }
- 
- static inline void native_load_gdt(const struct desc_ptr *dtr)
-@@ -246,8 +254,10 @@ static inline void native_load_tls(struc
- 	unsigned int i;
- 	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
- 
-+	pax_open_kernel();
- 	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- 		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
-+	pax_close_kernel();
- }
- 
- #define _LDT_empty(info)				\
-@@ -309,7 +319,7 @@ static inline void set_desc_limit(struct
- 	desc->limit = (limit >> 16) & 0xf;
- }
- 
--static inline void _set_gate(int gate, unsigned type, void *addr,
-+static inline void _set_gate(int gate, unsigned type, const void *addr,
- 			     unsigned dpl, unsigned ist, unsigned seg)
- {
- 	gate_desc s;
-@@ -327,7 +337,7 @@ static inline void _set_gate(int gate, u
-  * Pentium F0 0F bugfix can have resulted in the mapped
-  * IDT being write-protected.
-  */
--static inline void set_intr_gate(unsigned int n, void *addr)
-+static inline void set_intr_gate(unsigned int n, const void *addr)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
-@@ -356,19 +366,19 @@ static inline void alloc_intr_gate(unsig
- /*
-  * This routine sets up an interrupt gate at directory privilege level 3.
-  */
--static inline void set_system_intr_gate(unsigned int n, void *addr)
-+static inline void set_system_intr_gate(unsigned int n, const void *addr)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
- }
- 
--static inline void set_system_trap_gate(unsigned int n, void *addr)
-+static inline void set_system_trap_gate(unsigned int n, const void *addr)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
- }
- 
--static inline void set_trap_gate(unsigned int n, void *addr)
-+static inline void set_trap_gate(unsigned int n, const void *addr)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
-@@ -377,19 +387,31 @@ static inline void set_trap_gate(unsigne
- static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
- {
- 	BUG_ON((unsigned)n > 0xFF);
--	_set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
-+	_set_gate(n, GATE_TASK, (const void *)0, 0, 0, (gdt_entry<<3));
- }
- 
--static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
-+static inline void set_intr_gate_ist(int n, const void *addr, unsigned ist)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
- }
- 
--static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist)
-+static inline void set_system_intr_gate_ist(int n, const void *addr, unsigned ist)
- {
- 	BUG_ON((unsigned)n > 0xFF);
- 	_set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
- }
- 
-+#ifdef CONFIG_X86_32
-+static inline void set_user_cs(unsigned long base, unsigned long limit, int cpu)
-+{
-+	struct desc_struct d;
-+
-+	if (likely(limit))
-+		limit = (limit - 1UL) >> PAGE_SHIFT;
-+	pack_descriptor(&d, base, limit, 0xFB, 0xC);
-+	write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_CS, &d, \
                DESCTYPE_S);
-+}
-+#endif
-+
- #endif /* _ASM_X86_DESC_H */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/device.h \
                linux-2.6.34.1/arch/x86/include/asm/device.h
---- linux-2.6.34.1/arch/x86/include/asm/device.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/device.h	2010-07-07 09:04:45.000000000 -0400
-@@ -6,7 +6,7 @@ struct dev_archdata {
- 	void	*acpi_handle;
- #endif
- #ifdef CONFIG_X86_64
--struct dma_map_ops *dma_ops;
-+	const struct dma_map_ops *dma_ops;
- #endif
- #if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)
- 	void *iommu; /* hook for IOMMU specific extension */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/dma-mapping.h \
                linux-2.6.34.1/arch/x86/include/asm/dma-mapping.h
---- linux-2.6.34.1/arch/x86/include/asm/dma-mapping.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/dma-mapping.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -26,9 +26,9 @@ extern int iommu_merge;
- extern struct device x86_dma_fallback_dev;
- extern int panic_on_overflow;
- 
--extern struct dma_map_ops *dma_ops;
-+extern const struct dma_map_ops *dma_ops;
- 
--static inline struct dma_map_ops *get_dma_ops(struct device *dev)
-+static inline const struct dma_map_ops *get_dma_ops(struct device *dev)
- {
- #ifdef CONFIG_X86_32
- 	return dma_ops;
-@@ -45,7 +45,7 @@ static inline struct dma_map_ops *get_dm
- /* Make sure we keep the same behaviour */
- static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	if (ops->mapping_error)
- 		return ops->mapping_error(dev, dma_addr);
- 
-@@ -123,7 +123,7 @@ static inline void *
- dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- 		gfp_t gfp)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 	void *memory;
- 
- 	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
-@@ -150,7 +150,7 @@ dma_alloc_coherent(struct device *dev, s
- static inline void dma_free_coherent(struct device *dev, size_t size,
- 				     void *vaddr, dma_addr_t bus)
- {
--	struct dma_map_ops *ops = get_dma_ops(dev);
-+	const struct dma_map_ops *ops = get_dma_ops(dev);
- 
- 	WARN_ON(irqs_disabled());       /* for portability */
- 
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/e820.h \
                linux-2.6.34.1/arch/x86/include/asm/e820.h
---- linux-2.6.34.1/arch/x86/include/asm/e820.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/e820.h	2010-07-07 09:04:45.000000000 -0400
-@@ -64,7 +64,7 @@ struct e820map {
- #define ISA_START_ADDRESS	0xa0000
- #define ISA_END_ADDRESS		0x100000
- 
--#define BIOS_BEGIN		0x000a0000
-+#define BIOS_BEGIN		0x000c0000
- #define BIOS_END		0x00100000
- 
- #ifdef __KERNEL__
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/elf.h \
                linux-2.6.34.1/arch/x86/include/asm/elf.h
---- linux-2.6.34.1/arch/x86/include/asm/elf.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/elf.h	2010-07-07 09:04:45.000000000 -0400
-@@ -237,7 +237,25 @@ extern int force_personality32;
-    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.  */
- 
-+#ifdef CONFIG_PAX_SEGMEXEC
-+#define ELF_ET_DYN_BASE		((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? \
                SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2)
-+#else
- #define ELF_ET_DYN_BASE		(TASK_SIZE / 3 * 2)
-+#endif
-+
-+#ifdef CONFIG_PAX_ASLR
-+#ifdef CONFIG_X86_32
-+#define PAX_ELF_ET_DYN_BASE	0x10000000UL
-+
-+#define PAX_DELTA_MMAP_LEN	(current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
-+#define PAX_DELTA_STACK_LEN	(current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
-+#else
-+#define PAX_ELF_ET_DYN_BASE	0x400000UL
-+
-+#define PAX_DELTA_MMAP_LEN	((test_thread_flag(TIF_IA32)) ? 16 : TASK_SIZE_MAX_SHIFT \
                - PAGE_SHIFT - 3)
-+#define PAX_DELTA_STACK_LEN	((test_thread_flag(TIF_IA32)) ? 16 : \
                TASK_SIZE_MAX_SHIFT - PAGE_SHIFT - 3)
-+#endif
-+#endif
- 
- /* 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,
-@@ -291,8 +309,7 @@ do {									\
- #define ARCH_DLINFO							\
- do {									\
- 	if (vdso_enabled)						\
--		NEW_AUX_ENT(AT_SYSINFO_EHDR,				\
--			    (unsigned long)current->mm->context.vdso);	\
-+		NEW_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso);\
- } while (0)
- 
- #define AT_SYSINFO		32
-@@ -303,7 +320,7 @@ do {									\
- 
- #endif /* !CONFIG_X86_32 */
- 
--#define VDSO_CURRENT_BASE	((unsigned long)current->mm->context.vdso)
-+#define VDSO_CURRENT_BASE	(current->mm->context.vdso)
- 
- #define VDSO_ENTRY							\
- 	((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall))
-@@ -317,7 +334,4 @@ extern int arch_setup_additional_pages(s
- extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
- #define compat_arch_setup_additional_pages	syscall32_setup_pages
- 
--extern unsigned long arch_randomize_brk(struct mm_struct *mm);
--#define arch_randomize_brk arch_randomize_brk
--
- #endif /* _ASM_X86_ELF_H */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/futex.h \
                linux-2.6.34.1/arch/x86/include/asm/futex.h
---- linux-2.6.34.1/arch/x86/include/asm/futex.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/futex.h	2010-07-07 09:04:45.000000000 -0400
-@@ -11,17 +11,54 @@
- #include <asm/processor.h>
- #include <asm/system.h>
- 
-+#ifdef CONFIG_X86_32
- #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)	\
-+	asm volatile(						\
-+		     "movw\t%w6, %%ds\n"			\
-+		     "1:\t" insn "\n"				\
-+		     "2:\tpushl\t%%ss\n"			\
-+		     "\tpopl\t%%ds\n"				\
-+		     "\t.section .fixup,\"ax\"\n"		\
-+		     "3:\tmov\t%3, %1\n"			\
-+		     "\tjmp\t2b\n"				\
-+		     "\t.previous\n"				\
-+		     _ASM_EXTABLE(1b, 3b)			\
-+		     : "=r" (oldval), "=r" (ret), "+m" (*uaddr)	\
-+		     : "i" (-EFAULT), "0" (oparg), "1" (0), "r" (__USER_DS))
-+
-+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg)	\
-+	asm volatile("movw\t%w7, %%es\n"			\
-+		     "1:\tmovl\t%%es:%2, %0\n"			\
-+		     "\tmovl\t%0, %3\n"				\
-+		     "\t" insn "\n"				\
-+		     "2:\t" LOCK_PREFIX "cmpxchgl %3, %%es:%2\n"\
-+		     "\tjnz\t1b\n"				\
-+		     "3:\tpushl\t%%ss\n"			\
-+		     "\tpopl\t%%es\n"				\
-+		     "\t.section .fixup,\"ax\"\n"		\
-+		     "4:\tmov\t%5, %1\n"			\
-+		     "\tjmp\t3b\n"				\
-+		     "\t.previous\n"				\
-+		     _ASM_EXTABLE(1b, 4b)			\
-+		     _ASM_EXTABLE(2b, 4b)			\
-+		     : "=&a" (oldval), "=&r" (ret),		\
-+		       "+m" (*uaddr), "=&r" (tem)		\
-+		     : "r" (oparg), "i" (-EFAULT), "1" (0), "r" (__USER_DS))
-+#else
-+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)	\
-+	typecheck(u32 *, uaddr);				\
- 	asm volatile("1:\t" insn "\n"				\
- 		     "2:\t.section .fixup,\"ax\"\n"		\
- 		     "3:\tmov\t%3, %1\n"			\
- 		     "\tjmp\t2b\n"				\
- 		     "\t.previous\n"				\
- 		     _ASM_EXTABLE(1b, 3b)			\
--		     : "=r" (oldval), "=r" (ret), "+m" (*uaddr)	\
-+		     : "=r" (oldval), "=r" (ret),		\
-+		       "+m" (*(uaddr + PAX_USER_SHADOW_BASE / 4))\
- 		     : "i" (-EFAULT), "0" (oparg), "1" (0))
- 
- #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg)	\
-+	typecheck(u32 *, uaddr);				\
- 	asm volatile("1:\tmovl	%2, %0\n"			\
- 		     "\tmovl\t%0, %3\n"				\
- 		     "\t" insn "\n"				\
-@@ -34,10 +71,12 @@
- 		     _ASM_EXTABLE(1b, 4b)			\
- 		     _ASM_EXTABLE(2b, 4b)			\
- 		     : "=&a" (oldval), "=&r" (ret),		\
--		       "+m" (*uaddr), "=&r" (tem)		\
-+		       "+m" (*(uaddr + PAX_USER_SHADOW_BASE / 4)),\
-+		       "=&r" (tem)				\
- 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
-+#endif
- 
--static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
-+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
- {
- 	int op = (encoded_op >> 28) & 7;
- 	int cmp = (encoded_op >> 24) & 15;
-@@ -61,11 +100,20 @@ static inline int futex_atomic_op_inuser
- 
- 	switch (op) {
- 	case FUTEX_OP_SET:
-+#ifdef CONFIG_X86_32
-+		__futex_atomic_op1("xchgl %0, %%ds:%2", ret, oldval, uaddr, oparg);
-+#else
- 		__futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
-+#endif
- 		break;
- 	case FUTEX_OP_ADD:
-+#ifdef CONFIG_X86_32
-+		__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %%ds:%2", ret, oldval,
-+				   uaddr, oparg);
-+#else
- 		__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
- 				   uaddr, oparg);
-+#endif
- 		break;
- 	case FUTEX_OP_OR:
- 		__futex_atomic_op2("orl %4, %3", ret, oldval, uaddr, oparg);
-@@ -109,7 +157,7 @@ static inline int futex_atomic_op_inuser
- 	return ret;
- }
- 
--static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-+static inline int futex_atomic_cmpxchg_inatomic(u32 __user *uaddr, int oldval,
- 						int newval)
- {
- 
-@@ -119,17 +167,31 @@ static inline int futex_atomic_cmpxchg_i
- 		return -ENOSYS;
- #endif
- 
--	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
-+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- 		return -EFAULT;
- 
--	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
--		     "2:\t.section .fixup, \"ax\"\n"
-+	asm volatile(
-+#ifdef CONFIG_X86_32
-+		     "\tmovw %w5, %%ds\n"
-+		     "1:\t" LOCK_PREFIX "cmpxchgl %3, %%ds:%1\n"
-+		     "2:\tpushl   %%ss\n"
-+		     "\tpopl    %%ds\n"
-+#else
-+		     "1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
-+		     "2:\n"
-+#endif
-+		     "\t.section .fixup, \"ax\"\n"
- 		     "3:\tmov     %2, %0\n"
- 		     "\tjmp     2b\n"
- 		     "\t.previous\n"
- 		     _ASM_EXTABLE(1b, 3b)
-+#ifdef CONFIG_X86_32
- 		     : "=a" (oldval), "+m" (*uaddr)
-+		     : "i" (-EFAULT), "r" (newval), "0" (oldval), "r" (__USER_DS)
-+#else
-+		     : "=a" (oldval), "+m" (*(uaddr + PAX_USER_SHADOW_BASE / 4))
- 		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
-+#endif
- 		     : "memory"
- 	);
- 
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/i387.h \
                linux-2.6.34.1/arch/x86/include/asm/i387.h
---- linux-2.6.34.1/arch/x86/include/asm/i387.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/i387.h	2010-07-07 09:04:45.000000000 -0400
-@@ -70,6 +70,11 @@ static inline int fxrstor_checking(struc
- {
- 	int err;
- 
-+#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
-+	if ((unsigned long)fx < PAX_USER_SHADOW_BASE)
-+		fx = (struct i387_fxsave_struct *)((void *)fx + PAX_USER_SHADOW_BASE);
-+#endif
-+
- 	asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
- 		     "2:\n"
- 		     ".section .fixup,\"ax\"\n"
-@@ -115,6 +120,11 @@ static inline int fxsave_user(struct i38
- {
- 	int err;
- 
-+#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
-+	if ((unsigned long)fx < PAX_USER_SHADOW_BASE)
-+		fx = (struct i387_fxsave_struct __user *)((void __user *)fx + \
                PAX_USER_SHADOW_BASE);
-+#endif
-+
- 	asm volatile("1:  rex64/fxsave (%[fx])\n\t"
- 		     "2:\n"
- 		     ".section .fixup,\"ax\"\n"
-@@ -205,13 +215,8 @@ static inline int fxrstor_checking(struc
- }
- 
- /* We need a safe address that is cheap to find and that is already
--   in L1 during context switch. The best choices are unfortunately
--   different for UP and SMP */
--#ifdef CONFIG_SMP
--#define safe_address (__per_cpu_offset[0])
--#else
--#define safe_address (kstat_cpu(0).cpustat.user)
--#endif
-+   in L1 during context switch. */
-+#define safe_address (init_tss[smp_processor_id()].x86_tss.sp0)
- 
- /*
-  * These must be called with preempt disabled
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/io.h \
                linux-2.6.34.1/arch/x86/include/asm/io.h
---- linux-2.6.34.1/arch/x86/include/asm/io.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/io.h	2010-07-07 09:04:45.000000000 -0400
-@@ -213,6 +213,17 @@ extern void iounmap(volatile void __iome
- 
- #include <linux/vmalloc.h>
- 
-+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-+static inline int valid_phys_addr_range(unsigned long addr, size_t count)
-+{
-+	return ((addr + count + PAGE_SIZE - 1) >> PAGE_SHIFT) < (1 << \
                (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0;
-+}
-+
-+static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-+{
-+	return (pfn + (count >> PAGE_SHIFT)) < (1 << (boot_cpu_data.x86_phys_bits - \
                PAGE_SHIFT)) ? 1 : 0;
-+}
-+
- /*
-  * Convert a virtual cached pointer to an uncached pointer
-  */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/iommu.h \
                linux-2.6.34.1/arch/x86/include/asm/iommu.h
---- linux-2.6.34.1/arch/x86/include/asm/iommu.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/iommu.h	2010-07-07 09:04:45.000000000 -0400
-@@ -1,7 +1,7 @@
- #ifndef _ASM_X86_IOMMU_H
- #define _ASM_X86_IOMMU_H
- 
--extern struct dma_map_ops nommu_dma_ops;
-+extern const struct dma_map_ops nommu_dma_ops;
- extern int force_iommu, no_iommu;
- extern int iommu_detected;
- extern int iommu_pass_through;
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/irqflags.h \
                linux-2.6.34.1/arch/x86/include/asm/irqflags.h
---- linux-2.6.34.1/arch/x86/include/asm/irqflags.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/irqflags.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -142,6 +142,11 @@ static inline unsigned long __raw_local_
- 	sti;					\
- 	sysexit
- 
-+#define GET_CR0_INTO_RDI		mov %cr0, %rdi
-+#define SET_RDI_INTO_CR0		mov %rdi, %cr0
-+#define GET_CR3_INTO_RDI		mov %cr3, %rdi
-+#define SET_RDI_INTO_CR3		mov %rdi, %cr3
-+
- #else
- #define INTERRUPT_RETURN		iret
- #define ENABLE_INTERRUPTS_SYSEXIT	sti; sysexit
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/kvm_host.h \
                linux-2.6.34.1/arch/x86/include/asm/kvm_host.h
---- linux-2.6.34.1/arch/x86/include/asm/kvm_host.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/kvm_host.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -547,7 +547,7 @@ struct kvm_x86_ops {
- 	const struct trace_print_flags *exit_reasons_str;
- };
- 
--extern struct kvm_x86_ops *kvm_x86_ops;
-+extern const struct kvm_x86_ops *kvm_x86_ops;
- 
- int kvm_mmu_module_init(void);
- void kvm_mmu_module_exit(void);
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/local.h \
                linux-2.6.34.1/arch/x86/include/asm/local.h
---- linux-2.6.34.1/arch/x86/include/asm/local.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/local.h	2010-07-07 09:04:45.000000000 -0400
-@@ -18,26 +18,90 @@ typedef struct {
- 
- static inline void local_inc(local_t *l)
- {
--	asm volatile(_ASM_INC "%0"
-+	asm volatile(_ASM_INC "%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_DEC "%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
- 		     : "+m" (l->a.counter));
- }
- 
- static inline void local_dec(local_t *l)
- {
--	asm volatile(_ASM_DEC "%0"
-+	asm volatile(_ASM_DEC "%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_INC "%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
- 		     : "+m" (l->a.counter));
- }
- 
- static inline void local_add(long i, local_t *l)
- {
--	asm volatile(_ASM_ADD "%1,%0"
-+	asm volatile(_ASM_ADD "%1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_SUB "%1,%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
- 		     : "+m" (l->a.counter)
- 		     : "ir" (i));
- }
- 
- static inline void local_sub(long i, local_t *l)
- {
--	asm volatile(_ASM_SUB "%1,%0"
-+	asm volatile(_ASM_SUB "%1,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_ADD "%1,%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
- 		     : "+m" (l->a.counter)
- 		     : "ir" (i));
- }
-@@ -55,7 +119,24 @@ static inline int local_sub_and_test(lon
- {
- 	unsigned char c;
- 
--	asm volatile(_ASM_SUB "%2,%0; sete %1"
-+	asm volatile(_ASM_SUB "%2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_ADD "%2,%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (l->a.counter), "=qm" (c)
- 		     : "ir" (i) : "memory");
- 	return c;
-@@ -73,7 +154,24 @@ static inline int local_dec_and_test(loc
- {
- 	unsigned char c;
- 
--	asm volatile(_ASM_DEC "%0; sete %1"
-+	asm volatile(_ASM_DEC "%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_INC "%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (l->a.counter), "=qm" (c)
- 		     : : "memory");
- 	return c != 0;
-@@ -91,7 +189,24 @@ static inline int local_inc_and_test(loc
- {
- 	unsigned char c;
- 
--	asm volatile(_ASM_INC "%0; sete %1"
-+	asm volatile(_ASM_INC "%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_DEC "%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sete %1\n"
- 		     : "+m" (l->a.counter), "=qm" (c)
- 		     : : "memory");
- 	return c != 0;
-@@ -110,7 +225,24 @@ static inline int local_add_negative(lon
- {
- 	unsigned char c;
- 
--	asm volatile(_ASM_ADD "%2,%0; sets %1"
-+	asm volatile(_ASM_ADD "%2,%0\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_SUB "%2,%0\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
-+		     "sets %1\n"
- 		     : "+m" (l->a.counter), "=qm" (c)
- 		     : "ir" (i) : "memory");
- 	return c;
-@@ -133,7 +265,23 @@ static inline long local_add_return(long
- #endif
- 	/* Modern 486+ processor */
- 	__i = i;
--	asm volatile(_ASM_XADD "%0, %1;"
-+	asm volatile(_ASM_XADD "%0, %1\n"
-+
-+#ifdef CONFIG_PAX_REFCOUNT
-+#ifdef CONFIG_X86_32
-+		     "into\n0:\n"
-+#else
-+		     "jno 0f\n"
-+		     "int $4\n0:\n"
-+#endif
-+		     ".pushsection .fixup,\"ax\"\n"
-+		     "1:\n"
-+		     _ASM_MOV "%0,%1\n"
-+		     "jmp 0b\n"
-+		     ".popsection\n"
-+		     _ASM_EXTABLE(0b, 1b)
-+#endif
-+
- 		     : "+r" (i), "+m" (l->a.counter)
- 		     : : "memory");
- 	return i + __i;
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/mc146818rtc.h \
                linux-2.6.34.1/arch/x86/include/asm/mc146818rtc.h
---- linux-2.6.34.1/arch/x86/include/asm/mc146818rtc.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/mc146818rtc.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -81,8 +81,8 @@ static inline unsigned char current_lock
- #else
- #define lock_cmos_prefix(reg) do {} while (0)
- #define lock_cmos_suffix(reg) do {} while (0)
--#define lock_cmos(reg)
--#define unlock_cmos()
-+#define lock_cmos(reg) do {} while (0)
-+#define unlock_cmos() do {} while (0)
- #define do_i_have_lock_cmos() 0
- #define current_lock_cmos_reg() 0
- #endif
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/microcode.h \
                linux-2.6.34.1/arch/x86/include/asm/microcode.h
---- linux-2.6.34.1/arch/x86/include/asm/microcode.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/microcode.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -12,13 +12,13 @@ struct device;
- enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
- 
- struct microcode_ops {
--	enum ucode_state (*request_microcode_user) (int cpu,
-+	enum ucode_state (* const request_microcode_user) (int cpu,
- 				const void __user *buf, size_t size);
- 
--	enum ucode_state (*request_microcode_fw) (int cpu,
-+	enum ucode_state (* const request_microcode_fw) (int cpu,
- 				struct device *device);
- 
--	void (*microcode_fini_cpu) (int cpu);
-+	void (* const microcode_fini_cpu) (int cpu);
- 
- 	/*
- 	 * The generic 'microcode_core' part guarantees that
-@@ -38,18 +38,18 @@ struct ucode_cpu_info {
- extern struct ucode_cpu_info ucode_cpu_info[];
- 
- #ifdef CONFIG_MICROCODE_INTEL
--extern struct microcode_ops * __init init_intel_microcode(void);
-+extern const struct microcode_ops * __init init_intel_microcode(void);
- #else
--static inline struct microcode_ops * __init init_intel_microcode(void)
-+static inline const struct microcode_ops * __init init_intel_microcode(void)
- {
- 	return NULL;
- }
- #endif /* CONFIG_MICROCODE_INTEL */
- 
- #ifdef CONFIG_MICROCODE_AMD
--extern struct microcode_ops * __init init_amd_microcode(void);
-+extern const struct microcode_ops * __init init_amd_microcode(void);
- #else
--static inline struct microcode_ops * __init init_amd_microcode(void)
-+static inline const struct microcode_ops * __init init_amd_microcode(void)
- {
- 	return NULL;
- }
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/mman.h \
                linux-2.6.34.1/arch/x86/include/asm/mman.h
---- linux-2.6.34.1/arch/x86/include/asm/mman.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/mman.h	2010-07-07 09:04:45.000000000 -0400
-@@ -5,4 +5,14 @@
- 
- #include <asm-generic/mman.h>
- 
-+#ifdef __KERNEL__
-+#ifndef __ASSEMBLY__
-+#ifdef CONFIG_X86_32
-+#define arch_mmap_check	i386_mmap_check
-+int i386_mmap_check(unsigned long addr, unsigned long len,
-+		unsigned long flags);
-+#endif
-+#endif
-+#endif
-+
- #endif /* _ASM_X86_MMAN_H */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/mmu.h \
                linux-2.6.34.1/arch/x86/include/asm/mmu.h
---- linux-2.6.34.1/arch/x86/include/asm/mmu.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/mmu.h	2010-07-07 09:04:45.000000000 -0400
-@@ -9,10 +9,23 @@
-  * we put the segment information here.
-  */
- typedef struct {
--	void *ldt;
-+	struct desc_struct *ldt;
- 	int size;
- 	struct mutex lock;
--	void *vdso;
-+	unsigned long vdso;
-+
-+#ifdef CONFIG_X86_32
-+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
-+	unsigned long user_cs_base;
-+	unsigned long user_cs_limit;
-+
-+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
-+	cpumask_t cpu_user_cs_mask;
-+#endif
-+
-+#endif
-+#endif
-+
- } mm_context_t;
- 
- #ifdef CONFIG_SMP
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/mmu_context.h \
                linux-2.6.34.1/arch/x86/include/asm/mmu_context.h
---- linux-2.6.34.1/arch/x86/include/asm/mmu_context.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/mmu_context.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -24,6 +24,21 @@ void destroy_context(struct mm_struct *m
- 
- static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
- {
-+
-+#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
-+	unsigned int i;
-+	pgd_t *pgd;
-+
-+	pax_open_kernel();
-+	pgd = get_cpu_pgd(smp_processor_id());
-+	for (i = USER_PGD_PTRS; i < 2 * USER_PGD_PTRS; ++i)
-+		if (paravirt_enabled())
-+			set_pgd(pgd+i, native_make_pgd(0));
-+		else
-+			pgd[i] = native_make_pgd(0);
-+	pax_close_kernel();
-+#endif
-+
- #ifdef CONFIG_SMP
- 	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
- 		percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
-@@ -34,27 +49,70 @@ static inline void switch_mm(struct mm_s
- 			     struct task_struct *tsk)
- {
- 	unsigned cpu = smp_processor_id();
-+#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
-+	int tlbstate = TLBSTATE_OK;
-+#endif
- 
- 	if (likely(prev != next)) {
- 		/* stop flush ipis for the previous mm */
- 		cpumask_clear_cpu(cpu, mm_cpumask(prev));
- #ifdef CONFIG_SMP
-+#ifdef CONFIG_X86_32
-+		tlbstate = percpu_read(cpu_tlbstate.state);
-+#endif
- 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
- 		percpu_write(cpu_tlbstate.active_mm, next);
- #endif
- 		cpumask_set_cpu(cpu, mm_cpumask(next));
- 
- 		/* Re-load page tables */
-+#ifdef CONFIG_PAX_PER_CPU_PGD
-+		pax_open_kernel();
-+		__clone_user_pgds(get_cpu_pgd(cpu), next->pgd, USER_PGD_PTRS);
-+		__shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd, USER_PGD_PTRS);
-+		pax_close_kernel();
-+		load_cr3(get_cpu_pgd(cpu));
-+#else
- 		load_cr3(next->pgd);
-+#endif
- 
- 		/*
- 		 * load the LDT, if the LDT is different:
- 		 */
- 		if (unlikely(prev->context.ldt != next->context.ldt))
- 			load_LDT_nolock(&next->context);
--	}
-+
-+#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
-+		if (!(__supported_pte_mask & _PAGE_NX)) {
-+			smp_mb__before_clear_bit();
-+			cpu_clear(cpu, prev->context.cpu_user_cs_mask);
-+			smp_mb__after_clear_bit();
-+			cpu_set(cpu, next->context.cpu_user_cs_mask);
-+		}
-+#endif
-+
-+#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || \
                defined(CONFIG_PAX_SEGMEXEC))
-+		if (unlikely(prev->context.user_cs_base != next->context.user_cs_base ||
-+			     prev->context.user_cs_limit != next->context.user_cs_limit))
-+			set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
- #ifdef CONFIG_SMP
-+		else if (unlikely(tlbstate != TLBSTATE_OK))
-+			set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
-+#endif
-+#endif
-+
-+	}
- 	else {
-+
-+#ifdef CONFIG_PAX_PER_CPU_PGD
-+		pax_open_kernel();
-+		__clone_user_pgds(get_cpu_pgd(cpu), next->pgd, USER_PGD_PTRS);
-+		__shadow_user_pgds(get_cpu_pgd(cpu) + USER_PGD_PTRS, next->pgd, USER_PGD_PTRS);
-+		pax_close_kernel();
-+		load_cr3(get_cpu_pgd(cpu));
-+#endif
-+
-+#ifdef CONFIG_SMP
- 		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
- 		BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
- 
-@@ -63,11 +121,28 @@ static inline void switch_mm(struct mm_s
- 			 * tlb flush IPI delivery. We must reload CR3
- 			 * to make sure to use no freed page tables.
- 			 */
-+
-+#ifndef CONFIG_PAX_PER_CPU_PGD
- 			load_cr3(next->pgd);
-+#endif
-+
- 			load_LDT_nolock(&next->context);
-+
-+#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC)
-+			if (!(__supported_pte_mask & _PAGE_NX))
-+				cpu_set(cpu, next->context.cpu_user_cs_mask);
-+#endif
-+
-+#if defined(CONFIG_X86_32) && (defined(CONFIG_PAX_PAGEEXEC) || \
                defined(CONFIG_PAX_SEGMEXEC))
-+#ifdef CONFIG_PAX_PAGEEXEC
-+			if (!((next->pax_flags & MF_PAX_PAGEEXEC) && (__supported_pte_mask & _PAGE_NX)))
-+#endif
-+				set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu);
-+#endif
-+
- 		}
--	}
- #endif
-+	}
- }
- 
- #define activate_mm(prev, next)			\
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/module.h \
                linux-2.6.34.1/arch/x86/include/asm/module.h
---- linux-2.6.34.1/arch/x86/include/asm/module.h	2010-07-05 14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/module.h	2010-07-07 09:04:45.000000000 -0400
-@@ -59,13 +59,31 @@
- #error unknown processor family
- #endif
- 
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+#define MODULE_PAX_UDEREF "UDEREF "
-+#else
-+#define MODULE_PAX_UDEREF ""
-+#endif
-+
- #ifdef CONFIG_X86_32
- # ifdef CONFIG_4KSTACKS
- #  define MODULE_STACKSIZE "4KSTACKS "
- # else
- #  define MODULE_STACKSIZE ""
- # endif
--# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
-+# ifdef CONFIG_PAX_KERNEXEC
-+#  define MODULE_PAX_KERNEXEC "KERNEXEC "
-+# else
-+#  define MODULE_PAX_KERNEXEC ""
-+# endif
-+# ifdef CONFIG_GRKERNSEC
-+#  define MODULE_GRSEC "GRSECURITY "
-+# else
-+#  define MODULE_GRSEC ""
-+# endif
-+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE MODULE_GRSEC \
                MODULE_PAX_KERNEXEC MODULE_PAX_UDEREF
-+#else
-+# define MODULE_ARCH_VERMAGIC MODULE_PAX_UDEREF
- #endif
- 
- #endif /* _ASM_X86_MODULE_H */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/page_32_types.h \
                linux-2.6.34.1/arch/x86/include/asm/page_32_types.h
---- linux-2.6.34.1/arch/x86/include/asm/page_32_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/page_32_types.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -15,6 +15,10 @@
-  */
- #define __PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
- 
-+#ifdef CONFIG_PAX_PAGEEXEC
-+#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
-+#endif
-+
- #ifdef CONFIG_4KSTACKS
- #define THREAD_ORDER	0
- #else
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/page_64_types.h \
                linux-2.6.34.1/arch/x86/include/asm/page_64_types.h
---- linux-2.6.34.1/arch/x86/include/asm/page_64_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/page_64_types.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -39,6 +39,9 @@
- #define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
- #define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
- 
-+#define ktla_ktva(addr)		(addr)
-+#define ktva_ktla(addr)		(addr)
-+
- /* See Documentation/x86/x86_64/mm.txt for a description of the memory map. */
- #define __PHYSICAL_MASK_SHIFT	46
- #define __VIRTUAL_MASK_SHIFT	47
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/paravirt.h \
                linux-2.6.34.1/arch/x86/include/asm/paravirt.h
---- linux-2.6.34.1/arch/x86/include/asm/paravirt.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/paravirt.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -720,6 +720,21 @@ static inline void __set_fixmap(unsigned
- 	pv_mmu_ops.set_fixmap(idx, phys, flags);
- }
- 
-+#ifdef CONFIG_PAX_KERNEXEC
-+static inline unsigned long pax_open_kernel(void)
-+{
-+	return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_open_kernel);
-+}
-+
-+static inline unsigned long pax_close_kernel(void)
-+{
-+	return PVOP_CALL0(unsigned long, pv_mmu_ops.pax_close_kernel);
-+}
-+#else
-+static inline unsigned long pax_open_kernel(void) { return 0; }
-+static inline unsigned long pax_close_kernel(void) { return 0; }
-+#endif
-+
- #if defined(CONFIG_SMP) && defined(CONFIG_PARAVIRT_SPINLOCKS)
- 
- static inline int arch_spin_is_locked(struct arch_spinlock *lock)
-@@ -936,7 +951,7 @@ extern void default_banner(void);
- 
- #define PARA_PATCH(struct, off)        ((PARAVIRT_PATCH_##struct + (off)) / 4)
- #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4)
--#define PARA_INDIRECT(addr)	*%cs:addr
-+#define PARA_INDIRECT(addr)	*%ss:addr
- #endif
- 
- #define INTERRUPT_RETURN						\
-@@ -1013,6 +1028,21 @@ extern void default_banner(void);
- 	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit),	\
- 		  CLBR_NONE,						\
- 		  jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit))
-+
-+#define GET_CR0_INTO_RDI				\
-+	call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0);	\
-+	mov %rax,%rdi
-+
-+#define SET_RDI_INTO_CR0				\
-+	call PARA_INDIRECT(pv_cpu_ops+PV_CPU_write_cr0)
-+
-+#define GET_CR3_INTO_RDI				\
-+	call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr3);	\
-+	mov %rax,%rdi
-+
-+#define SET_RDI_INTO_CR3				\
-+	call PARA_INDIRECT(pv_mmu_ops+PV_MMU_write_cr3)
-+
- #endif	/* CONFIG_X86_32 */
- 
- #endif /* __ASSEMBLY__ */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/paravirt_types.h \
                linux-2.6.34.1/arch/x86/include/asm/paravirt_types.h
---- linux-2.6.34.1/arch/x86/include/asm/paravirt_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/paravirt_types.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -312,6 +312,12 @@ struct pv_mmu_ops {
- 	   an mfn.  We can tell which is which from the index. */
- 	void (*set_fixmap)(unsigned /* enum fixed_addresses */ idx,
- 			   phys_addr_t phys, pgprot_t flags);
-+
-+#ifdef CONFIG_PAX_KERNEXEC
-+	unsigned long (*pax_open_kernel)(void);
-+	unsigned long (*pax_close_kernel)(void);
-+#endif
-+
- };
- 
- struct arch_spinlock;
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pci_x86.h \
                linux-2.6.34.1/arch/x86/include/asm/pci_x86.h
---- linux-2.6.34.1/arch/x86/include/asm/pci_x86.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pci_x86.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -89,16 +89,16 @@ extern int (*pcibios_enable_irq)(struct 
- extern void (*pcibios_disable_irq)(struct pci_dev *dev);
- 
- struct pci_raw_ops {
--	int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
-+	int (* const read)(unsigned int domain, unsigned int bus, unsigned int devfn,
- 						int reg, int len, u32 *val);
--	int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
-+	int (* const write)(unsigned int domain, unsigned int bus, unsigned int devfn,
- 						int reg, int len, u32 val);
- };
- 
--extern struct pci_raw_ops *raw_pci_ops;
--extern struct pci_raw_ops *raw_pci_ext_ops;
-+extern const struct pci_raw_ops *raw_pci_ops;
-+extern const struct pci_raw_ops *raw_pci_ext_ops;
- 
--extern struct pci_raw_ops pci_direct_conf1;
-+extern const struct pci_raw_ops pci_direct_conf1;
- extern bool port_cf9_safe;
- 
- /* arch_initcall level */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgalloc.h \
                linux-2.6.34.1/arch/x86/include/asm/pgalloc.h
---- linux-2.6.34.1/arch/x86/include/asm/pgalloc.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgalloc.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -63,6 +63,13 @@ static inline void pmd_populate_kernel(s
- 				       pmd_t *pmd, pte_t *pte)
- {
- 	paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
-+	set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
-+}
-+
-+static inline void pmd_populate_user(struct mm_struct *mm,
-+				       pmd_t *pmd, pte_t *pte)
-+{
-+	paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT);
- 	set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
- }
- 
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable-2level.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable-2level.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable-2level.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable-2level.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -18,7 +18,9 @@ static inline void native_set_pte(pte_t 
- 
- static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
- {
-+	pax_open_kernel();
- 	*pmdp = pmd;
-+	pax_close_kernel();
- }
- 
- static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable-3level.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable-3level.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable-3level.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable-3level.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -38,12 +38,16 @@ static inline void native_set_pte_atomic
- 
- static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
- {
-+	pax_open_kernel();
- 	set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd));
-+	pax_close_kernel();
- }
- 
- static inline void native_set_pud(pud_t *pudp, pud_t pud)
- {
-+	pax_open_kernel();
- 	set_64bit((unsigned long long *)(pudp), native_pud_val(pud));
-+	pax_close_kernel();
- }
- 
- /*
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -76,12 +76,51 @@ extern struct list_head pgd_list;
- 
- #define arch_end_context_switch(prev)	do {} while(0)
- 
-+#define pax_open_kernel()	native_pax_open_kernel()
-+#define pax_close_kernel()	native_pax_close_kernel()
- #endif	/* CONFIG_PARAVIRT */
- 
-+#define  __HAVE_ARCH_PAX_OPEN_KERNEL
-+#define  __HAVE_ARCH_PAX_CLOSE_KERNEL
-+
-+#ifdef CONFIG_PAX_KERNEXEC
-+static inline unsigned long native_pax_open_kernel(void)
-+{
-+	unsigned long cr0;
-+
-+	preempt_disable();
-+	barrier();
-+	cr0 = read_cr0() ^ X86_CR0_WP;
-+	BUG_ON(unlikely(cr0 & X86_CR0_WP));
-+	write_cr0(cr0);
-+	return cr0 ^ X86_CR0_WP;
-+}
-+
-+static inline unsigned long native_pax_close_kernel(void)
-+{
-+	unsigned long cr0;
-+
-+	cr0 = read_cr0() ^ X86_CR0_WP;
-+	BUG_ON(unlikely(!(cr0 & X86_CR0_WP)));
-+	write_cr0(cr0);
-+	barrier();
-+	preempt_enable_no_resched();
-+	return cr0 ^ X86_CR0_WP;
-+}
-+#else
-+static inline unsigned long native_pax_open_kernel(void) { return 0; }
-+static inline unsigned long native_pax_close_kernel(void) { return 0; }
-+#endif
-+
- /*
-  * The following only work if pte_present() is true.
-  * Undefined behaviour if not..
-  */
-+static inline int pte_user(pte_t pte)
-+{
-+	return pte_val(pte) & _PAGE_USER;
-+}
-+
- static inline int pte_dirty(pte_t pte)
- {
- 	return pte_flags(pte) & _PAGE_DIRTY;
-@@ -169,9 +208,29 @@ static inline pte_t pte_wrprotect(pte_t 
- 	return pte_clear_flags(pte, _PAGE_RW);
- }
- 
-+static inline pte_t pte_mkread(pte_t pte)
-+{
-+	return __pte(pte_val(pte) | _PAGE_USER);
-+}
-+
- static inline pte_t pte_mkexec(pte_t pte)
- {
--	return pte_clear_flags(pte, _PAGE_NX);
-+#ifdef CONFIG_X86_PAE
-+	if (__supported_pte_mask & _PAGE_NX)
-+		return pte_clear_flags(pte, _PAGE_NX);
-+	else
-+#endif
-+		return pte_set_flags(pte, _PAGE_USER);
-+}
-+
-+static inline pte_t pte_exprotect(pte_t pte)
-+{
-+#ifdef CONFIG_X86_PAE
-+	if (__supported_pte_mask & _PAGE_NX)
-+		return pte_set_flags(pte, _PAGE_NX);
-+	else
-+#endif
-+		return pte_clear_flags(pte, _PAGE_USER);
- }
- 
- static inline pte_t pte_mkdirty(pte_t pte)
-@@ -304,6 +363,15 @@ pte_t *populate_extra_pte(unsigned long 
- #endif
- 
- #ifndef __ASSEMBLY__
-+
-+#ifdef CONFIG_PAX_PER_CPU_PGD
-+extern pgd_t cpu_pgd[NR_CPUS][PTRS_PER_PGD];
-+static inline pgd_t *get_cpu_pgd(unsigned int cpu)
-+{
-+	return cpu_pgd[cpu];
-+}
-+#endif
-+
- #include <linux/mm_types.h>
- 
- static inline int pte_none(pte_t pte)
-@@ -474,7 +542,7 @@ static inline pud_t *pud_offset(pgd_t *p
- 
- static inline int pgd_bad(pgd_t pgd)
- {
--	return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE;
-+	return (pgd_flags(pgd) & ~(_PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE;
- }
- 
- static inline int pgd_none(pgd_t pgd)
-@@ -497,7 +565,12 @@ static inline int pgd_none(pgd_t pgd)
-  * pgd_offset() returns a (pgd_t *)
-  * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
-  */
--#define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address)))
-+#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
-+
-+#ifdef CONFIG_PAX_PER_CPU_PGD
-+#define pgd_offset_cpu(cpu, address) (get_cpu_pgd(cpu) + pgd_index(address))
-+#endif
-+
- /*
-  * a shortcut which implies the use of the kernel's pgd, instead
-  * of a process's
-@@ -508,6 +581,20 @@ static inline int pgd_none(pgd_t pgd)
- #define KERNEL_PGD_BOUNDARY	pgd_index(PAGE_OFFSET)
- #define KERNEL_PGD_PTRS		(PTRS_PER_PGD - KERNEL_PGD_BOUNDARY)
- 
-+#ifdef CONFIG_X86_32
-+#define USER_PGD_PTRS		KERNEL_PGD_BOUNDARY
-+#else
-+#define TASK_SIZE_MAX_SHIFT CONFIG_TASK_SIZE_MAX_SHIFT
-+#define USER_PGD_PTRS		(_AC(1,UL) << (TASK_SIZE_MAX_SHIFT - PGDIR_SHIFT))
-+
-+#ifdef CONFIG_PAX_MEMORY_UDEREF
-+#define PAX_USER_SHADOW_BASE	(_AC(1,UL) << TASK_SIZE_MAX_SHIFT)
-+#else
-+#define PAX_USER_SHADOW_BASE	(_AC(0,UL))
-+#endif
-+
-+#endif
-+
- #ifndef __ASSEMBLY__
- 
- extern int direct_gbpages;
-@@ -613,11 +700,23 @@ static inline void ptep_set_wrprotect(st
-  * dst and src can be on the same page, but the range must not overlap,
-  * and must not cross a page boundary.
-  */
--static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
-+static inline void clone_pgd_range(pgd_t *dst, const pgd_t *src, int count)
- {
--       memcpy(dst, src, count * sizeof(pgd_t));
-+	pax_open_kernel();
-+	while (count--)
-+		*dst++ = *src++;
-+	pax_close_kernel();
- }
- 
-+#ifdef CONFIG_PAX_PER_CPU_PGD
-+extern void __clone_user_pgds(pgd_t *dst, const pgd_t *src, int count);
-+#endif
-+
-+#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
-+extern void __shadow_user_pgds(pgd_t *dst, const pgd_t *src, int count);
-+#else
-+static inline void __shadow_user_pgds(pgd_t *dst, const pgd_t *src, int count) {}
-+#endif
- 
- #include <asm-generic/pgtable.h>
- #endif	/* __ASSEMBLY__ */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable_32.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable_32.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable_32.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable_32.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -25,8 +25,6 @@
- struct mm_struct;
- struct vm_area_struct;
- 
--extern pgd_t swapper_pg_dir[1024];
--
- static inline void pgtable_cache_init(void) { }
- static inline void check_pgt_cache(void) { }
- void paging_init(void);
-@@ -47,6 +45,11 @@ extern void set_pmd_pfn(unsigned long, u
- # include <asm/pgtable-2level.h>
- #endif
- 
-+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-+#ifdef CONFIG_X86_PAE
-+extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
-+#endif
-+
- #if defined(CONFIG_HIGHPTE)
- #define __KM_PTE			\
- 	(in_nmi() ? KM_NMI_PTE : 	\
-@@ -71,7 +74,9 @@ extern void set_pmd_pfn(unsigned long, u
- /* Clear a kernel PTE and flush it from the TLB */
- #define kpte_clear_flush(ptep, vaddr)		\
- do {						\
-+	pax_open_kernel();			\
- 	pte_clear(&init_mm, (vaddr), (ptep));	\
-+	pax_close_kernel();			\
- 	__flush_tlb_one((vaddr));		\
- } while (0)
- 
-@@ -83,6 +88,9 @@ do {						\
- 
- #endif /* !__ASSEMBLY__ */
- 
-+#define HAVE_ARCH_UNMAPPED_AREA
-+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-+
- /*
-  * kern_addr_valid() is (1) for FLATMEM and (0) for
-  * SPARSEMEM and DISCONTIGMEM
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable_32_types.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable_32_types.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable_32_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable_32_types.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -8,7 +8,7 @@
-  */
- #ifdef CONFIG_X86_PAE
- # include <asm/pgtable-3level_types.h>
--# define PMD_SIZE	(1UL << PMD_SHIFT)
-+# define PMD_SIZE	(_AC(1, UL) << PMD_SHIFT)
- # define PMD_MASK	(~(PMD_SIZE - 1))
- #else
- # include <asm/pgtable-2level_types.h>
-@@ -46,6 +46,19 @@ extern bool __vmalloc_start_set; /* set 
- # define VMALLOC_END	(FIXADDR_START - 2 * PAGE_SIZE)
- #endif
- 
-+#ifdef CONFIG_PAX_KERNEXEC
-+#ifndef __ASSEMBLY__
-+extern unsigned char MODULES_EXEC_VADDR[];
-+extern unsigned char MODULES_EXEC_END[];
-+#endif
-+#include <asm/boot.h>
-+#define ktla_ktva(addr)		(addr + LOAD_PHYSICAL_ADDR + PAGE_OFFSET)
-+#define ktva_ktla(addr)		(addr - LOAD_PHYSICAL_ADDR - PAGE_OFFSET)
-+#else
-+#define ktla_ktva(addr)		(addr)
-+#define ktva_ktla(addr)		(addr)
-+#endif
-+
- #define MODULES_VADDR	VMALLOC_START
- #define MODULES_END	VMALLOC_END
- #define MODULES_LEN	(MODULES_VADDR - MODULES_END)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable_64.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable_64.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable_64.h	2010-07-05 14:24:10.000000000 \
                -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable_64.h	2010-07-07 09:04:45.000000000 \
                -0400
-@@ -16,10 +16,13 @@
- 
- extern pud_t level3_kernel_pgt[512];
- extern pud_t level3_ident_pgt[512];
-+extern pud_t level3_vmalloc_pgt[512];
-+extern pud_t level3_vmemmap_pgt[512];
-+extern pud_t level2_vmemmap_pgt[512];
- extern pmd_t level2_kernel_pgt[512];
- extern pmd_t level2_fixmap_pgt[512];
--extern pmd_t level2_ident_pgt[512];
--extern pgd_t init_level4_pgt[];
-+extern pmd_t level2_ident_pgt[512*2];
-+extern pgd_t init_level4_pgt[512];
- 
- #define swapper_pg_dir init_level4_pgt
- 
-@@ -74,7 +77,9 @@ static inline pte_t native_ptep_get_and_
- 
- static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
- {
-+	pax_open_kernel();
- 	*pmdp = pmd;
-+	pax_close_kernel();
- }
- 
- static inline void native_pmd_clear(pmd_t *pmd)
-@@ -94,7 +99,9 @@ static inline void native_pud_clear(pud_
- 
- static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
- {
-+	pax_open_kernel();
- 	*pgdp = pgd;
-+	pax_close_kernel();
- }
- 
- static inline void native_pgd_clear(pgd_t *pgd)
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable_64_types.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable_64_types.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable_64_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable_64_types.h	2010-07-07 \
                09:04:45.000000000 -0400
-@@ -59,5 +59,7 @@ typedef struct { pteval_t pte; } pte_t;
- #define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
- #define MODULES_END      _AC(0xffffffffff000000, UL)
- #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
-+#define MODULES_EXEC_VADDR MODULES_VADDR
-+#define MODULES_EXEC_END MODULES_END
- 
- #endif /* _ASM_X86_PGTABLE_64_DEFS_H */
-diff -urNp linux-2.6.34.1/arch/x86/include/asm/pgtable_types.h \
                linux-2.6.34.1/arch/x86/include/asm/pgtable_types.h
---- linux-2.6.34.1/arch/x86/include/asm/pgtable_types.h	2010-07-05 \
                14:24:10.000000000 -0400
-+++ linux-2.6.34.1/arch/x86/include/asm/pgtable_types.h	2010-07-07 \
                09:04:46.000000000 -0400
-@@ -16,12 +16,11 @@
- #define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
- #define _PAGE_BIT_PAT		7	/* on 4KB pages */
- #define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
--#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
-+#define _PAGE_BIT_SPECIAL	9	/* special mappings, no associated struct page */
- #define _PAGE_BIT_IOMAP		10	/* flag used to indicate IO mapping */
- #define _PAGE_BIT_HIDDEN	11	/* hidden by kmemcheck */
- #define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
--#define _PAGE_BIT_SPECIAL	_PAGE_BIT_UNUSED1
--#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_UNUSED1
-+#define _PAGE_BIT_CPA_TEST	_PAGE_BIT_SPECIAL
- #define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check \
                */
- 
- /* If _PAGE_BIT_PRESENT is clear, we use these: */
-@@ -39,7 +38,6 @@
- #define _PAGE_DIRTY	(_AT(pteval_t, 1) << _PAGE_BIT_DIRTY)
- #define _PAGE_PSE	(_AT(pteval_t, 1) << _PAGE_BIT_PSE)
- #define _PAGE_GLOBAL	(_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
--#define _PAGE_UNUSED1	(_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1)
- #define _PAGE_IOMAP	(_AT(pteval_t, 1) << _PAGE_BIT_IOMAP)
- #define _PAGE_PAT	(_AT(pteval_t, 1) << _PAGE_BIT_PAT)
- #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
-@@ -55,8 +53,10 @@
- 
- #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
- #define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_NX)
--#else
-+#elif defined(CONFIG_KMEMCHECK)
- #define _PAGE_NX	(_AT(pteval_t, 0))
-+#else
-+#define _PAGE_NX	(_AT(pteval_t, 1) << _PAGE_BIT_HIDDEN)
- #endif
- 
- #define _PAGE_FILE	(_AT(pteval_t, 1) << _PAGE_BIT_FILE)
-@@ -93,6 +93,9 @@
- #define PAGE_READONLY_EXEC	__pgprot(_PAGE_PRESENT | _PAGE_USER |	\
- 					 _PAGE_ACCESSED)
- 
-+#define PAGE_READONLY_NOEXEC PAGE_READONLY
-+#define PAGE_SHARED_NOEXEC PAGE_SHARED
-+
- #define __PAGE_KERNEL_EXEC						\
- 	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL)
- #define __PAGE_KERNEL		(__PAGE_KERNEL_EXEC | _PAGE_NX)
-@@ -103,8 +106,8 @@
- #define __PAGE_KERNEL_WC		(__PAGE_KERNEL | _PAGE_CACHE_WC)
- #define __PAGE_KERNEL_NOCACHE		(__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT)
- #define __PAGE_KERNEL_UC_MINUS		(__PAGE_KE


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic